Simon: A Memory Game

Dependencies:   4DGL-uLCD-SE PinDetect mbed

main.cpp

Committer:
cmathis
Date:
2014-10-21
Revision:
2:c92f0e749b94
Parent:
1:cd222334a4fe

File content as of revision 2:c92f0e749b94:

/*********************************/
// 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);
AnalogIn pot(p19);

// variable declarations
int levels[16];
int levelsIndex;
int level;
int buttonPressed;
int buttonPushes;
int failed;
int start = 1;
int randomSeed;
float volume;

// 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) {
        
        volume = pot.read();
        
        // 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){
            volume = pot.read();
            wait(0.1);
        }
        
        // 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 == 10 && 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.color(BLUE);
    uLCD.text_width(2);
    uLCD.text_height(2);
    uLCD.locate(2, 3);
    uLCD.printf("SIMON");
    
    // start up LED/uLCD sequence
    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;
    
    // display the current level on the uLCD
    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, volume);
                led1 = 0;
                wait(0.025);
                break;
            case 2:
                led2 = 1;
                mySpeaker.PlayNote(554.00, 0.50, volume);
                led2 = 0;
                wait(0.025);
                break;
            case 3:
                led3 = 1;
                mySpeaker.PlayNote(440.00, 0.50, volume);
                led3 = 0;
                wait(0.025);
                break;
            case 4:
                led4 = 1;
                mySpeaker.PlayNote(329.63, 0.50, volume);
                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, volume);
    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, volume);
    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, volume);
    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, volume);
    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, volume);
    mySpeaker.PlayNote(139.00, 0.60, volume);
    mySpeaker.PlayNote(131.00, 0.60, volume);
    mySpeaker.PlayNote(123.00, 1.60, volume);
    
}

// 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, volume);
    wait(time);
    mySpeaker.PlayNote(349.23, 0.17, volume);
    wait(time);
    
    mySpeaker.PlayNote(311.13, 0.33, volume);
    wait(time);
    mySpeaker.PlayNote(311.13, 0.17, volume);
    wait(time);
    mySpeaker.PlayNote(311.13, 0.33, volume);
    wait(time);
    mySpeaker.PlayNote(349.23, 0.17, volume);
    wait(time);
    
    mySpeaker.PlayNote(392.00, 0.33, volume);
    wait(time);
    mySpeaker.PlayNote(392.00, 0.17, volume);
    wait(time);
    mySpeaker.PlayNote(392.00, 0.165, volume);
    wait(time);
    mySpeaker.PlayNote(349.23, 0.165, volume);
    wait(time);
    mySpeaker.PlayNote(311.13, 0.17, volume);
    wait(time);
    
    mySpeaker.PlayNote(349.23, 0.165, volume);
    wait(time);
    mySpeaker.PlayNote(392.00, 0.165, volume);
    wait(time);
    mySpeaker.PlayNote(349.23, 0.17, volume);
    wait(time);
    mySpeaker.PlayNote(311.13, 0.33, volume);
    wait(time);
    mySpeaker.PlayNote(293.66, 0.17, volume);
    wait(time);
    
    mySpeaker.PlayNote(311.13, 0.5, volume);
    
}