MSP430 Guitar Hero
ECE 2049 Lab 2
4.5.2022 - 4.19.2022 | WPI
OBJECTIVE
This project uses a MSP430 microcontroller to implement a simple version of the game Guitar Hero, where a song is played with 4 multi-colored LEDs flashing, each corresponding to the note of the song, and the user interacts by pressing the corresponding button within the duration of the note. The objective of this project includes understanding the operation of digital I/O and MSP430 timer and writing software that depends critically on the passage of time.
Button Configuration
Referencing the MSP430F5529 schematic, each button was configured to a corresponding port & pin using bitwise operations. Pull-up resistor was enabled to prevent the pins from being left floating and to ensure that the pin is connected to a voltage source, producing a high logic level when the button is not pressed, or to ground for a low logic level when it is pressed.
Since the low level logic is set to indicate the button being pressed, if statement was implemented in readButtons function, where the condition checks to see if the value at pin 0 of port 7 corresponds to 0 for the button S1.
Its return value is initialized to 0 and is programmed so that if S1 is pressed alone, to 0x01 (0000 0001b), if S3 alone is pressed, sets to 0x04 (0000 0100b), and if both S1 and S3 is pressed, it sets to 0x05 (0000 0101b).
source: MSP430 Schematic
User LED Configuration
Similar to the button configuration, each LED was configured to its corresponding port & pin. These LEDs are different from the 4 multi-colored LEDs that light up for the duration of the note. These two user LEDs were each green and red-colored and were used in a countdown at the start of the game, and to indicate whether the user pressed the correct button or not during the game. (green for correct, red for incorrect)
In the setUserLED function, a parameter inbits was used to control which LED was getting was lighting up. For instance, if a char value of ‘1’ was passed in as an argument, LED1 would turn on, if ‘2’ was passed in, LED2 would turn on, and if ‘3’ was passed in, both the LEDs would turn on. Else, if any other values were passed in, it would turn them off.
Buzzer Configuration
BuzzerOn function was modified so that it takes a parameter called note that takes an unsigned char symbol as an argument to decide which note to play using if statements.
Buzzer uses the MSP430 built-in timer, Time_B module, to generate different pitch of the sound by varying the duty cycle of PWM signal (Pulse Width Modulation). Depending of the note that is passed in as an argument, the PWM period (TB0CCR0) is set differently. These PMW values were calculated by the equation,
1 / note frequency = ( PWM + 1 ) * ( 1 / ACLK frequency)
where the ACLK frequency is 32768 Hz.
Timer Configuration
TASSEL was selected to 1 which corresponds to ACLK with the frequency of 32768 Hz. To achieve the resolution of at least 0.005 seconds, PWM had to be set to a value that returns a period value less that 0.005 sec. However, the most ideal PWM value of 163 actually gives a cycle period of about 5.00488 millisecond which is 4.8828125t*10^-6 seconds slower than the actual time.
In the interrupt function, the timer count, that is initialized to 0 at the start of the timer, increments by 1, as well as the leap count. When the leap count gets to 1024, (on the 1024th cycle), the error of 4.8828125t*10^-6 seconds accumulates to be exactly 0.005 seconds, so the timer count increments by 2 and leap count is reset to 0. This ensures that every 1024 cycle, when the clock is 0.005 seconds behind the actual time, the error is compensated by adding another count.
PROGRAM DESIGN
For the organization and the coherence of the code, inside an infinite while loop, a switch statement was used to break down the overall system of the game into different cases, such as displaying a welcome screen, doing a countdown, and the user interaction. This made it fairly easy to switch between different stages of the game, for instance, resetting it to a welcome screen after the game was done.
Inside the main function
In the case 2 of the switch statement, playGame function is called which plays the song as well as check the user’s button input within the duration of the note. The timer starts when case 2 is called then it calls the playGame function which runs the for loop through the arrays of note, duration and LED that are defined in global and turns the buzzer on at a particular pitch for a corresponding duration and flash the corresponding LED as well. The timer function is used for the program design instead of software delay function since the timer function allows to execute various tasks while the time is kept track of. On the other hand, software delay is a blocking function which makes it impossible to play buzzer, flash LED and check user input during the duration of the note.
In the first part of the playGame function, it sets the local time equal to the global time, and the while loop stays true only for the duration of the note inside the for loop. Since the button should be checked only once during the time of the note and not repeatedly, an if statement is implemented to ensure that input buttons are only checked when the button has not been pressed yet. Once the button is pressed, it goes onto an if/else statement that checks if the button input was correct or not where it displays the status on the screen.
arrays of note, duration and LED
first half of the function
In the second half of the playGame function, it allows us to
second half of the function