The University of Queensland
School of Information Technology and Electrical Engineering Semester 1, 2023
CSSE2010/CSSE7201 Assignment 2 Due: 4:00pm (AEST) Friday May 26, 2023
Weighting: 20% (100 marks)
As part of the assessment for this course, you are required to undertake an assignment which will test you against some of the more practical learning objectives of the course, namely your C programming skills applied to the ATmega324A microcontroller.
You are required to modify a program to implement additional features. The program is a basic template of the arcade game ‘Pong’ (described in detail on page 3). The AVR ATmega324A microcontroller runs the program and receives input from multiple sources and uses an LED matrix as a display for the game, with additional information being output to a serial terminal and – to be implemented as part of this assignment – a seven segment display and other devices.
The version of Pong provided to you has very basic functionality – it will present a start screen upon launch, respond to button presses or a terminal input ‘s’/‘S’ to start the game, then display the board for the game Pong with the player paddles and the ball. You can add features such as moving the player paddles, bouncing the ball off the walls and paddles, game scoring, pausing, sound effects etc. The various features have different levels of difficulty and will each contribute a certain number of marks. Note that marks are awarded based on demonstrated functionality only.
Don’t Panic!
You have been provided with approximately 1500 lines of code to start with – many of which are comments. Whilst this code may seem confusing, you don’t need to understand all of it. The code provided does a lot of the hard work for you, e.g., interacting with the serial port and the LED matrix display. To start with, you should read the header (.h) files provided along with game.c and project.c. You may need to look at the AVR C Library documentation to understand some of the functions used. An intro/getting started video is available on Blackboard, which contains a demonstration of some of the expected functionality to be implemented and walks through setting the project up with the provided base code.
Academic Merit, Plagiarism, Collusion and Other Misconduct
You should read and understand the statement on academic merit, plagiarism, collusion and other misconduct contained within the course profile and the document referenced in that course profile. You must not show your code to or share your code with any other student under any circumstances. You must not post your code to public discussion forums or save your code in publicly accessible repositories. You must not look at or copy code from any other student. All submitted files will be subject to electronic plagiarism detection and misconduct proceedings will be instituted against students where plagiarism or collusion is suspected. The electronic plagiarism detection can detect similarities in code structure even if comments, variable names, formatting etc. are modified. If you copy code, you will be caught.
Grading Note
As described in the course profile, if you do not score at least 10% on this assignment (before any late penalty) then your course grade will be capped at a 3 (i.e. you will fail the course). If you do not obtain at least 50% on this assignment (before any late penalty), then your course grade will be capped at a 5. Your assignment mark (after any late penalty) will count 20% towards your final course grade.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 1
Program Description
The program you will be provided with has several C files which contain groups of related functions. The files provided are described below. The corresponding .h files (except for project.c) list the functions that are intended to be accessible from other files. You may modify any of the provided files. You must submit ALL files used to build your project, even if you have not modified some provided files. Many files make assumptions about which AVR ports are used to connect to various IO devices. You are encouraged not to change these.
• project.c – this is the main file that contains the game event loop and examples of how time- based events are implemented. You should read and understand this file.
• game.c/.h – this file contains the implementation of the game components and is used to store the state of the game. You should read this file and understand what representation is used for the game state and the ball and paddle positions. You will need to modify this file to add required functionality.
• display.c/.h – this file contains the implementation for displaying the current state of the board. This file contains useful functions for displaying the board to the LED matrix.
• buttons.c/.h – this contains the code which deals with the push buttons. It sets up pin change interrupts on those pins and records rising edges (buttons being pushed).
• ledmatrix.c/.h – this contains functions which give easier access to the services provided by the LED matrix. It makes use of the SPI routines implemented in spi.c.
• pixel_colour.h – this file contains definitions of some useful colours for use with the LED matrix.
• serialio.c/.h – this file is responsible for handling serial input and output using interrupts. It also maps the C standard IO routines (e.g. printf() and fgetc()) to use the serial interface so you are able to use printf() etc for debugging purposes if you wish. You should not need to look in this file, but you may be interested in how it works and the buffer sizes used for input and output (and what happens when the buffers fill up).
• terminalio.c/.h – this encapsulates the sending of various escape sequences which enable some control over terminal appearance and text placement – you can call these functions (declared in terminalio.h) instead of remembering various escape sequences. Additional information about terminal IO will be provided on the course Blackboard site.
• spi.c./h – this file encapsulates all SPI communication. Note that by default, all SPI communication uses busy waiting (i.e. polling) – the “send” routine returns only when the data is sent. If you need the CPU cycles for other activities, you may wish to consider converting this to interrupt based IO, similar to the way that serial IO is handled.
• timer0.c/.h – sets up a timer that is used to generate an interrupt every millisecond and update a global time value that is used to time various game events (such as the Pong ball movement). This can be useful for implementing any features that require precise timing.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 2
Pong Description
This assignment involves creating a replica of the classic arcade game ‘Pong’. Pong is a two-player game that simulates a game of table tennis. Each player has a ‘paddle’ on their side of the screen (left for Player 1 and right for Player 2), which they can control along the vertical axis. Each paddle can be used to deflect the ball, so that the ball can be rallied back and forth across the playing area. The goal of the game is to get the ball past the opposite player’s paddle so that it hits the back wall (scoring a point). This version of the game is over once a player reaches three points. An overview of the game is shown in Figure 1.
Figure 1: Pong playing field with labels.
The playing area is displayed on the 16 columns and 8 rows of the LED matrix, with each player’s paddle (displayed in green) starting in the centre of the vertical axis, and the ball (displayed in red) starting in (approximately) the centre of the board (at game coordinates (5, 4)). The back walls used to score points are displayed in yellow and confine the playing area to 12 columns and 8 rows. The top and bottom walls are not displayed in order to maximise the game space. The indexing for the playing area and the LED Matrix can be seen above in Figure 1.
Player Movement
Each of the paddles are two pixels in height and can be moved up and down along the outermost columns of the playing area. The paddles can only move along their respective column, as shown in Figure 2.
Figure 2: Directions that each paddle can move.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 3
The paddles are bounded by the top and bottom walls of the playing area and should not be allowed to exit the screen – partially or completely. The boundaries of the paddles are shown in Figure 3.
Figure 3: Player 1 at maximum paddle position and Player 2 at minimum paddle position. Note that the lighter shade of green represents the previous positions of the paddles, and the darker shade represents the final paddle positions.
Ball Movement
Note that all directions used in this specification are defined with the electrical connections of the LED matrix facing left i.e. the pins are on the left side. The pong ball can move along two axes; vertical and horizontal. Along the vertical axis the ball can move in three directions:
• UP (y direction is 1),
• STATIONARY (y direction is 0), or
• DOWN (y direction is –1).
Along the horizontal axis the ball can move in two directions:
• LEFT (x direction is –1), or
• RIGHT (x direction is 1).
This behaviour is illustrated in Figure 4.
The ball can move in any combination of vertical and horizontal directions, giving it six possible movements for each square (with restrictions when the ball is adjacent to a wall or paddle). In the supplied base code, the ball moves towards the top left of the display.
Figure 4: Directions in which the ball can move.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 4
While not implemented in the supplied base code, upon contact with the top or bottom wall, the ball’s vertical direction should be inverted (i.e., UP -> DOWN or DOWN -> UP). Similarly, if the ball contacts a player paddle, the ball’s horizontal direction should be inverted (i.e., LEFT -> RIGHT or RIGHT -> LEFT). On contact with the left or right walls, a point has been scored and the ball should be reset to the starting position. This behaviour will need to be implemented as part of the assignment. An example of the ball movement/bouncing behaviour is shown in Figure 5.
Figure 5: Example ball movement. Ball bounces off the bottom wall and scores a point for Player 1.
You can try out Pong for yourself on https://www.ponggame.org, but note that the version implemented as part of this assignment will vary in several ways, so the online version should be used as a reference only to understand the mechanics of the game.
Initial Operation
The provided program has very limited functionality. It will display a start screen which detects the rising edge on the push buttons B0, B1, B2 and B3, as well as the input terminal character ‘s’/’S’. Pressing any of these will start a game of Pong with the ball initially moving in the top left direction.
Once started, the program detects a rising edge on the button B3, but no action is taken on this input (this will need to be implemented as part of the Move Paddles with Buttons task).
Wiring Advice
When completing this assignment, you will need to make additional connections to the ATmega324A microcontroller to implement particular tasks. To do this, you will need to choose which pins to make these connections to. There are multiple ways to do this, so the exact wiring configuration will be left up to you, and you should communicate this using your submitted feature summary form (included at the end of this document. A standalone version is also available on Blackboard). Hint: consider what peripherals each feature requires and any pin limitations this imposes. Some connections are defined for you in the provided base code and are shown in grey below.
Port Pin 7
SPI connection to LED matrix
Baud rate: 19200
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023
Program Features
Marks will be awarded for features as described below. Part marks will be awarded if part of the specified functionality is demonstrated. Marks are awarded only on demonstrated functionality in the final submission – no marks are awarded for attempting to implement the functionality, no matter how much effort has gone into it. You may implement higher-level features without implementing all lower-level features if you like (subject to prerequisite requirements). The number of marks is not an indication of difficulty. It is much easier to earn the first 50% of marks than the second 50%.
You may modify any of the code provided (unless indicated otherwise) and use any of the code from learning lab sessions and/or posted on the course Blackboard site. For some of the easier features, the description below may tell you which code to modify or there may be comments in the supplied code to guide you.
NOTE: there is a pass hurdle of 10% for this assignment which can be achieved by completing the first two tasks (Start Screen and Move Paddles with Buttons).
Minimum Performance (Level 0 – Pass/Fail)
Your program must have at least the features present in the code supplied to you, i.e. it must build and run, show the start screen, and display the initial game when a button or ‘s’/ ‘S’ is pressed. No marks can be earned for other features unless this requirement is met, i.e. your assignment 2 mark will be zero.
Start Screen (Level 1 – 4 marks)
Modify the program so that when it starts (i.e. the AVR microcontroller is reset) it outputs your name and student number to the serial terminal. Do this by modifying the function start_screen() in file project.c.
Move Paddles with Buttons (Level 1 – 8 marks)
The provided program does not allow for the player paddles to be moved. Modify the program so when button B3 (connected to pin B3) is pressed, player #1’s paddle (the left paddle) moves upwards by one space and button B2 (connected to pin B2) is pressed, player #1’s paddle moves downwards by one space. Similarly, modify the program so that button B1 moves player #2’s paddle (the right paddle) upwards by one space and button B0 moves player #2’s paddle downwards by one space.
Note that no parts of the player paddles should be allowed to move outside of the playing area (as shown in Figure 3).
Note, the movements should occur once on each button press, there is no requirement for any action to occur if the button is held down (this will be implemented in a future task – Auto-Repeat Button Movement). Additionally, the behaviour when both B3 and B2 (or B1 and B0) are pressed is left up to you, so long as it is reasonable.
Hints: In the play_game()function in the file project.c, when button B3 is pressed, the function move_player_paddle(player, direction) in the file game.c is called. This function is currently empty, start by filling in the move_player_paddle function, there are some hints to get you started.
Move Paddles with Terminal Input (Level 1 – 4 marks)
The provided program does not register any terminal inputs once the game has started. Modify the program such that pressing ‘w’/‘W’ moves player #1 up one space, ‘s’/‘S’ and ‘d’/ ‘D’ moves player #1 down one space, ‘o’/‘O’ moves player #2 up one space, and ‘k’/‘K’ and ‘l’/ ‘L’ moves player #2 down one space. Note that both the lower case and upper case of each letter should execute these
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 6
movements as described. Also note that the inbuilt serial functionality handles keyboard inputs that are held down for you.
This layout of keys has been chosen to allow for two players to comfortably use the same keyboard to play. By having two keys to move each player downwards, the game can also be played at different angles comfortably, and on keyboards with different layouts.
On the start screen, the game can be started by pressing ‘s’ or ‘S’; Looking at the function start_screen() should give you an idea of how to read serial input from the terminal.
Note that if you press the directional arrows, they might also move the paddles in an unexpected direction, this is because they use escape characters that contain ‘A’ and ‘D’. We will not be considering escape characters when testing and will only use the letters of the alphabet and digits as potential inputs.
Ball Movement #1 (Bouncing off Walls) (Level 1 – 6 marks)
The supplied program contains code to update the ball position, however, it does not handle collisions with the walls. Modify the program so that the ball direction is updated on collision with a wall. The desired functionality is the following:
• If the ball collides with the top or bottom walls, invert the vertical direction (this corresponds to the ball bouncing).
• If the ball collides with the left or right walls, reset the ball position to the original position (game coordinates (5, 4)) (this corresponds to a point being scored). Hint: have a look at the functions supplied in game.c.
In the play_game() function in project.c, the function update_ball_position() from the file game.c is called every 500 ms. This function moves the ball once in the current horizontal direction and once in the current vertical direction. Modify the update_ball_position() function so that the appropriate action occurs upon collision with any walls (i.e., top, bottom, left or right).
The ball can ignore the paddles at this stage in the game – only consider the four walls.
Ball Movement #2 (Bouncing off Paddles) (Level 1 – 6 marks)
(This assumes that you have implemented “Ball Movement #1” above.)
Modify the program so that the ball bounces off the paddles. If the ball collides with a paddle, then the horizontal direction of the ball should be inverted. If the ball is travelling diagonally into the paddle, then it should bounce off the paddle (see Figure 6). In contrast, if the ball is travelling diagonally past the paddle, then it should not bounce (see Figure 7).
Figure 6: Ball travelling diagonally into a Figure 7: Ball travelling diagonally past a paddle. paddle.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 7
Programming Help
The paddle should not be able to move on-top of the ball (if the ball is in the same column as the paddles). An example of this invalid paddle movement can be seen in Figure 8.
Figure 8: Example of an invalid paddle move (the paddle should not be able to move on top of the ball).
If the ball is in the top or bottom row, you should resolve the change in direction from bouncing it off the wall before checking for collisions with the paddle.
Ball Movement #3 (Randomise Direction) (Level 1 – 6 marks)
(This assumes that you have implemented “Ball Movement #2” above.)
Modify the program so that the ball direction is randomised to make the game is less predictable. Specifically, you should implement the following changes:
• The horizontal and vertical direction of the ball should be randomised when the ball is reset (including at the start of the game).
• The vertical direction of the ball should be randomised when the ball bounces off a paddle. Your implementation will need to handle edge cases (i.e., ensure that the ball cannot go out of the
screen when the ball bounces off the paddles in the corners of the playing area).
For full marks in this section, you will need to find a way to seed the random number generator so that the direction appears ‘random’ (See rand() and srand()in stdlib.h). Note: the purpose of the seed is to generate a different random sequence each time the game is played. Hint: the time at the start of a game is a good source of randomness.
Game Score #1 (Terminal) and Game Over (Level 1 – 11 marks)
(This assumes that you have implemented “Ball Movement #1” above.)
Display the current score of both players to the terminal in a fixed position. Add appropriate text (e.g. “Player 1 Score:” and “Player 2 Score:” to the terminal display so it is clear where the score is displayed and which score refers to which player. Update the score display only when the score changes. The score must also be displayed when the game starts (a score of 0-0). The score must remain displayed on game-over (until a new game commences when the score should be reset).
Add functionality to detect if a player has won the game i.e. a player has reached a score of three. If a win is detected, then a message should be shown on the terminal indicating which player has won the game. The score should remain displayed together with the win message. When the game is over, pressing any button or the ‘s’/ ‘S’ keys should return the game to the splash screen. Some of this code has already been provided for you in project.c/game.c.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 8
Code Help, Add WeChat: cstutorcs
Game Score #2 (Seven Segment Display) (Level 1 – 7 marks)
(Assumes that “Game Score #1” is implemented.)
Display the score of both players on the seven-segment display. The left digit should display the score of Player 1 and the right digit should display the score of Player 2. The seven-segment display does not need to show the score on the start screen, however, should display the score throughout the game and after the game is over.
The seven-segment display should be updated on a regular interval and no display flickering or ‘ghosting’ (where digits can be faintly seen on the opposite display) should be apparent. Both digits should be of equal brightness. Include any connections required on your submitted feature summary form.
Game Speed (Level 2 – 6 marks)
Add the ability to toggle between different game speeds using the terminal. There should be 3 different game speeds:
• The slowest game speed should update the ball position once per 500 ms (milliseconds) and is the default game speed.
• The middle game speed should update the ball position once per 300 ms.
• The fastest game speed should update the ball position once per 200 ms.
The game speed may be changed at any point after the game has started by pressing:
• ‘1’ – select slowest game speed.
• ‘2’ – select medium game speed.
• ‘3’ – select fastest game speed.
If you like, you may also allow the game speed to be configured before the game begins, but this is not a requirement. You may also choose to retain the previous game speed when a new game starts, but this is also not a requirement.
The current game speed should be shown on the terminal as soon as the game starts and appropriate text should be added to the terminal display to indicate what the game speed is. As is the case for the game score, the current game speed text should only update when the game speed changes.
Game Pause (Level 2 – 6 marks)
Modify the program so that if the ‘p’/‘P’ key on the serial terminal is pressed then the game will pause. When ‘p’ or ‘P’ key on the serial terminal is pressed again, the game recommences. (All player movement buttons/key presses should be discarded whilst the game is paused – i.e., the paddles cannot be moved. You may wish to allow game features such as the speed to be adjusted while paused, but this is not required.) The ball update timing must be unaffected – e.g., if the pause happens 200 ms before the ball position is updated, then the ball position should not be updated until 200 ms after the game is resumed, not immediately upon resuming. Other functionality such as the seven segment display should be unaffected i.e. both digits of the seven segment display should still be shown (without ghosting etc.) if implemented.
Use LED L0 to indicate if the program is currently paused. If the game is paused LED L0 should be on, and if the game is not paused LED L0 should be off. Include any connections required on your submitted feature summary form. Also, display the message “Game paused” on the serial terminal when the game is paused. The message should only be shown while the game is paused, so when the game is unpaused, the pause message should be erased from the terminal. The existing messages shown on the terminal (e.g. game speed, game score) should remain while the game is paused.
Game Score #3 (LED Matrix) (Level 2 – 6 marks)
(Assumes that “Game Score #1” is implemented.)
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 9
Modify the program so that the current score is displayed on the LED matrix for 1.5 seconds after a goal is scored (overlaid on top of the game). The score for Player 1 should be displayed on the left half of the LED matrix and the score for Player 2 should be displayed on the right half of the LED matrix.
Figure 6: Example of LED Matrix Score.
The fonts for the digits to display can be found in the display.c file as an array of 16-bit unsigned integers (LED_DIGIT_FONTS). Each 16-bit digit font is stored as a 5×3 grid pattern going from Left-Right and Bottom-Top (padded with a leading 0). For example:
Figure 7: Digit layout for a 16-bit font with B15 Figure 8: Example layout of the 16-bit font for representing the MSB and B0 representing the digit two (0b0111100111001111).
You can implement a function to ‘draw’ and clear each of these digits. The score should be displayed using a colour that has not already been used (do not use the same colour as the ball, players or walls). All paddle movement inputs should be ignored while the score is displayed for the 1.5 seconds after a player scores a point, but you may choose how to handle other inputs such as the game speed and CPU player (if implemented). When the game ends, the score should remain on the display until a new game is started.
Rally Counter Display (Level 2 – 7 marks)
Modify the program so that the current ‘rally count’ for each round is displayed in the outermost columns. The rally count for both players should be reset to zero every time the game is started and every time a player scores a point. Each player’s rally count should be incremented each time the ball bounces off that player’s paddle. The rally count should start from the bottom of the matrix (row 0) and increase upwards (i.e., a rally count of four should fill the bottom four LED pixels in the corresponding column). If the rally count increases above the number of rows in the matrix, then it should wrap around and continue to increment as in Figure 10. For example, a rally count of 4 will display the same as a rally count of 12, 20, 28, etc.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 10
Display the current rally count for Player 1 in the left-most column of the LED matrix (column 0) and Player 2 in the right-most column of the LED matrix (column 15). You should use another colour that has not already been used and is not provided in any of the base code files.
An example of the rally counter in use can be seen in Figure 9.
Figure 9: Rally counter example. In the top frame each player has hit the ball three times (as seen in the rally counter columns). In the bottom frame, Player 2 hits the ball for a fourth time and Player 2’s rally counter is incremented.
Auto-Repeat Button Movement
Figure 10: Rally counter example of Player 2 rally count ‘wrapping around’.
(Level 2 – 7 marks)
Add auto-repeat support to the buttons which move the paddles – i.e., if one or more push buttons are held down then, after a short delay, they should act as if they are being repeatedly pressed. The auto- repeat behaviour on each button should be independent, e.g. if button 1 is in auto-repeat mode (i.e. you’re holding it down) and you also press and hold button 3 then button 1 should continue in auto- repeat mode and, after whatever delay you have set, button 3 would enter this mode also.
If the buttons for both moving up and moving down for a paddle are held down then the paddle should not move, but it may move up and then down (or vice versa) initially based on the first press of each button. In cases where an up/down keyboard character is also received while both buttons are held down, then you can choose to do something reasonable – this situation will not be explicitly tested when marking your assignment.
Joystick (Level 3 – 5 marks)
Add support to use the joystick to move Player 2 up and down. Only one axis of the joystick is required to be used – the L/R axis (note the joystick is mounted ‘sideways’ into the breadboard so this axis appears vertical when playing the game). Your implementation must include support for auto-repeat – if the joystick is held in one position then, after a short delay, the code should act as if the joystick was repeatedly moved in that direction.
Your movement must be reasonable – i.e. a reasonable player could stop at whichever space they desired. Your Player 2 paddle must be shown to move through all positions (i.e. it does not skip any rows) and be able to be stopped at that position if the joystick is released. Include any connections required on your submitted feature summary form.
CSSE2010/CSSE7201 Assignment 2, Semester 1, 2023 11
Code Help
Be aware that different joysticks may have different min/max/resting output voltages and you should allow for this in your implementation – your code will be marked with a different joystick to the one you test with.
Sound Effects (Level 3 – 5 marks)
Add sound effects to the program which are to be output using the piezo buzzer. Different sound effects (tones or combinations or tones) should be implemented for at least three events. (At least one of these must be a sequence of at least 4 tones for full marks.) For example, choose three of:
• • • • • • •
Paddles being moved.
Ball bouncing off a wall. Ball bouncing off a paddle. Goal being scored.
Game start-up.
Game over.
Constant background tune.
to toggle sound on and off, sound should be on when the game first starts. You may wish to (but are not required to) display a message on the serial terminal when the sounds