Simon: A Memory Game
Dependencies: 4DGL-uLCD-SE PinDetect mbed
Diff: main.cpp
- Revision:
- 0:64ea583d77e2
- Child:
- 1:cd222334a4fe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Oct 21 04:25:07 2014 +0000 @@ -0,0 +1,383 @@ +/*********************************/ +// ECE 4180 Lab 4 +// Colton Mathis, Taylor Hawley +/*********************************/ + +#include "mbed.h" +#include "uLCD_4DGL.h" +#include "PinDetect.h" +#include "Speaker.h" + +// pushbutton interrupts with debounce +PinDetect pb1(p25, PullUp); +PinDetect pb2(p26, PullUp); +PinDetect pb3(p23, PullUp); +PinDetect pb4(p24, PullUp); + +// four LED outputs +DigitalOut led1(p7); +DigitalOut led2(p9); +DigitalOut led3(p8); +DigitalOut led4(p6); + +// speaker object +Speaker mySpeaker(p21); + +// LCD object +uLCD_4DGL uLCD(p28, p27, p29); + +// analog input for seeding rand() function +AnalogIn adcReading(p18); + +// variable declarations +int levels[16]; +int levelsIndex; +int level; +int buttonPressed; +int buttonPushes; +int failed; +int start = 1; +int randomSeed; + +// function prototypes +void enableInterrupts(); +void disableInterrupts(); +void startGame(); +void setLevels(); +void playSequence(); +void pushOne(); +void pushTwo(); +void pushThree(); +void pushFour(); +void failedGame(); +void endGame(); + +int main() { + + // read in value from analog input as unsigned short instead of float + // and seed the rand() function with the value + randomSeed = adcReading.read_u16(); + srand(randomSeed); + uLCD.baudrate(3000000); + + while(1) { + + // only initialize these variables at the start of each game + if(start == 1){ + failed = 0; + level = 0; + buttonPressed = 0; + buttonPushes = 0; + levelsIndex = 0; + startGame(); + } + start = 0; + + // generate and play the sequence of LEDs (and sounds) that the player copies + setLevels(); + playSequence(); + + // enable the four pushbutton interrupts + enableInterrupts(); + + // wait in this loop until the user pushes buttons the same number of times as the current level + // or until the user has pushed an incorrect button + while(buttonPushes != level && failed == 0){ + wait(0.5); + } + + // if the user has failed, disable the pushbutton interrupts, notify the user that they failed, + // and then set start=1 so that the game restarts from level 1 + if(failed == 1){ + disableInterrupts(); + failedGame(); + start = 1; + } + + // if the user has completed all of the levels without failing, disable the pushbutton interrupts, + // notify the user that they won, and set start=1 so that the game restarts from level 1 + if(level == 5 && failed == 0){ + disableInterrupts(); + endGame(); + start = 1; + } + + // if the user has not failed or completed all of the levels, disable the interrupts and continue + disableInterrupts(); + + // set buttonpushes=0 to record the button presses for the next level + buttonPushes = 0; + + // wait a short amount of time before starting the next game + if(start==1){ + wait(2); + } + + } + +} + + +void enableInterrupts(){ + + // set the four pushbutton interrupts to trigger on a falling edge + pb1.attach_deasserted(&pushOne); + pb2.attach_deasserted(&pushTwo); + pb3.attach_deasserted(&pushThree); + pb4.attach_deasserted(&pushFour); + + // start the four interrupts (default sample frequency is 20ms) + pb1.setSampleFrequency(); + pb2.setSampleFrequency(); + pb3.setSampleFrequency(); + pb4.setSampleFrequency(); + +} + + +void disableInterrupts(){ + + // disable four interrupts by setting their service routine to NULL pointer + pb1.attach_deasserted(NULL); + pb2.attach_deasserted(NULL); + pb3.attach_deasserted(NULL); + pb4.attach_deasserted(NULL); + +} + +// this function is called at the beginning of the game +void startGame(){ + + uLCD.cls(); + uLCD.display_control(PORTRAIT); +// uLCD.media_init(); // initialize uSD card +// uLCD.set_sector_address(0x20,0xFF); // address of font file +// uLCD.set_font(MEDIAFONT); // load new font from uSD + uLCD.color(BLUE); + uLCD.text_width(2); + uLCD.text_height(2); + uLCD.locate(2, 3); + uLCD.printf("SIMON"); + + led1 = 1; + uLCD.filled_rectangle(0, 0, 63, 40, 0x00CC00); + wait(0.5); + led1 = 0; + uLCD.filled_rectangle(0, 0, 63, 40, 0x000000); + + led2 = 1; + uLCD.filled_rectangle(64, 0, 127, 40, 0xFF0000); + wait(0.5); + led2 = 0; + uLCD.filled_rectangle(64, 0, 127, 40, 0x000000); + + led3 = 1; + uLCD.filled_rectangle(64, 87, 127, 127, 0x0000FF); + wait(0.5); + led3 = 0; + uLCD.filled_rectangle(64, 87, 127, 127, 0x000000); + + led4 = 1; + uLCD.filled_rectangle(0, 87, 63, 127, 0xCCCC00); + wait(0.5); + led4 = 0; + uLCD.filled_rectangle(0, 87, 63, 127, 0x000000); + + wait(2); + + uLCD.cls(); + +} + + +void setLevels(){ + + // "levels" array is a sequence of numbers 1-4 that determines which LEDs will light up + // during a given level --- grows by 1 value each level + level++; + levels[level-1] = rand()%4 + 1; + + uLCD.color(BLUE); + uLCD.text_width(2); + uLCD.text_height(2); + uLCD.locate(2, 2); + uLCD.printf("Level"); + uLCD.locate(4, 4); + uLCD.printf("%d", level); + wait(1); + +} + + +void playSequence(){ + + // play the sequence of LEDs defined in the "levels" array along with the corresponding notes + for(int i = 0; i < level; i++){ + switch(levels[i]){ + case 1: + led1 = 1; + mySpeaker.PlayNote(659.26, 0.50, 0.2); + led1 = 0; + wait(0.025); + break; + case 2: + led2 = 1; + mySpeaker.PlayNote(554.00, 0.50, 0.2); + led2 = 0; + wait(0.025); + break; + case 3: + led3 = 1; + mySpeaker.PlayNote(440.00, 0.50, 0.2); + led3 = 0; + wait(0.025); + break; + case 4: + led4 = 1; + mySpeaker.PlayNote(329.63, 0.50, 0.2); + led4 = 0; + wait(0.025); + break; + default: + while(1){ + led1 = !led1; + wait(0.5); + } + } + } + +} + +// ISR for pushbutton 1 interrupt +void pushOne(){ + + buttonPushes++; + + led1 = 1; + mySpeaker.PlayNote(659.26, 0.25, 0.2); + led1 = 0; + + if(levels[buttonPushes-1] != 1){ + failed = 1; + } + +} + +// ISR for pushbutton 2 interrupt +void pushTwo(){ + + buttonPushes++; + + led2 = 1; + mySpeaker.PlayNote(554.00, 0.25, 0.2); + led2 = 0; + + if(levels[buttonPushes-1] != 2){ + failed = 1; + } + +} + +// ISR for pushbutton 3 interrupt +void pushThree(){ + + buttonPushes++; + + led3 = 1; + mySpeaker.PlayNote(440.00, 0.25, 0.2); + led3 = 0; + + if(levels[buttonPushes-1] != 3){ + failed = 1; + } + +} + +// ISR for pushbutton 4 interrupt +void pushFour(){ + + buttonPushes++; + + led4 = 1; + mySpeaker.PlayNote(329.63, 0.25, 0.2); + led4 = 0; + + if(levels[buttonPushes-1] != 4){ + failed = 1; + } + +} + +// this function is called when the user fails the game +void failedGame(){ + + uLCD.cls(); + uLCD.color(RED); + uLCD.text_width(2); + uLCD.text_height(2); + uLCD.locate(2, 2); + uLCD.printf("Game"); + uLCD.locate(2, 4); + uLCD.printf("Over"); + + + mySpeaker.PlayNote(147.00, 0.60, 1); + mySpeaker.PlayNote(139.00, 0.60, 1); + mySpeaker.PlayNote(131.00, 0.60, 1); + mySpeaker.PlayNote(123.00, 1.60, 1); + +} + +// this function is called if the user completes all levels +void endGame(){ + + uLCD.cls(); + uLCD.color(GREEN); + uLCD.text_width(2); + uLCD.text_height(2); + uLCD.locate(2, 2); + uLCD.printf("YOU"); + uLCD.locate(2, 4); + uLCD.printf("WIN!"); + + int time = 0.01; + + mySpeaker.PlayNote(392.00, 0.33, 0.2); + wait(time); + mySpeaker.PlayNote(349.23, 0.17, 0.2); + wait(time); + + mySpeaker.PlayNote(311.13, 0.33, 0.2); + wait(time); + mySpeaker.PlayNote(311.13, 0.17, 0.2); + wait(time); + mySpeaker.PlayNote(311.13, 0.33, 0.2); + wait(time); + mySpeaker.PlayNote(349.23, 0.17, 0.2); + wait(time); + + mySpeaker.PlayNote(392.00, 0.33, 0.2); + wait(time); + mySpeaker.PlayNote(392.00, 0.17, 0.2); + wait(time); + mySpeaker.PlayNote(392.00, 0.165, 0.2); + wait(time); + mySpeaker.PlayNote(349.23, 0.165, 0.2); + wait(time); + mySpeaker.PlayNote(311.13, 0.17, 0.2); + wait(time); + + mySpeaker.PlayNote(349.23, 0.165, 0.2); + wait(time); + mySpeaker.PlayNote(392.00, 0.165, 0.2); + wait(time); + mySpeaker.PlayNote(349.23, 0.17, 0.2); + wait(time); + mySpeaker.PlayNote(311.13, 0.33, 0.2); + wait(time); + mySpeaker.PlayNote(293.66, 0.17, 0.2); + wait(time); + + mySpeaker.PlayNote(311.13, 0.5, 0.2); + +} \ No newline at end of file