Simon: A Memory Game

Dependencies:   4DGL-uLCD-SE PinDetect mbed

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