Dependencies:   MCP23S17 RPG SDFileSystem TextLCD mbed wave_player

Fork of MCP23S17_Basic_IO_Demo by jim hamblen

main.cpp

Committer:
rpere
Date:
2013-03-04
Revision:
3:accf08e39ba0
Parent:
2:934a0500abde
Child:
4:9ea6afd40e7e

File content as of revision 3:accf08e39ba0:

// See http://mbed.org/users/romilly/notebook/mcp23s17-addressable-16-bit-io-expander-with-spi/
// MCP23S17 datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf
// uses MCP23S17 library version 0.4

#include "mbed.h"
#include "MCP23S17.h"
#include "TextLCD.h"
#include "RPG.h"
#include "wave_player.h" 
#include "SDFileSystem.h"

#define S_BEGIN 0
#define S_PLAY 1
#define S_VICTORY 2
#define S_DEFEAT 3

// Creates an initializes all necessary objects
void init();
// Obstains menu input and updates LCD text accordingly
int handleMenu();
// Plays the current sequence so far using timing appropriate to the chosen difficulty
void playSequence();
// Listens for the player move and returns a value indicating success or failure
int listenSequence();
// Re-initializes the game
void restart();


// Create SPI bus
SPI spi(p5, p6, p7);
// Create Text LCD Controller
TextLCD lcd(p21, p22, p23, p24, p25, p26);
// Create RPG interface
RPG rpg(p16,p17,p20);
// Create SD interface
SDFileSystem sd(p11, p12, p13, p14, "sd");
// Sound output
AnalogOut DACout(p18);
// Wave file player
wave_player waver(&DACout);
// Sound files
FILE *Sounds[11];

// Wiring Connections:
// mbed p5,p6,p7 are tied to MCP23S17 SI, SO, SCK pins
// mbed p8 to MCP23S17 CS
// MCP23S17 reset pin pulled high

// Chip addresses (opcodes)
char opcodes[3];
// Chip objects
MCP23S17* chips[3];


// Menu variables
char* menuOptions[] = {
    "      Easy     >",
    "<    Medium    >",
    "<     Hard      "
};
short menuState = 0;
short oldMenuState = -1;
short menuBuffer = 0;

// Difficulty settings
double timeoutVals[3] = { 2,  1.5, 1 };
double delayVals[3] = { 0.5, 0.3, 0.1};
short  victoryVals[3] = {4 , 6, 8};

// Game variables
short sequence[15];
short current = 0;
short gameState = 0;
short victory;
double timeout;
double delay;
char input = 0; // Push button input
int main()
{
    
    init();
    while (1) {
        int menuSelection;
        switch(gameState) 
        {
            case S_BEGIN:
                menuSelection = handleMenu();
                if(menuSelection > -1) 
                {
                    gameState = S_PLAY;
                    timeout = timeoutVals[menuSelection];
                    delay = delayVals[menuSelection];
                    victory = victoryVals[menuSelection];
                }
                break;

            case S_PLAY:
                playSequence();
                if(!listenSequence())
                    gameState = S_DEFEAT;
                else if(current == victory)
                    gameState = S_VICTORY;
                break;

            case S_VICTORY:
                lcd.cls();
                lcd.locate(0,0);
                lcd.printf("   YOU WON :D   ");
                lcd.printf("   <( . _ . )>  ");
                waver.play(Sounds[10]);
                rewind(Sounds[10]);
                wait(5);
                gameState = S_BEGIN;
                restart();
                break;

            case S_DEFEAT:
                lcd.cls();
                lcd.locate(0,0);
                lcd.printf("     DEFEAT     ");
                lcd.printf("   TRY HARDER   ");
                waver.play(Sounds[9]);
                rewind(Sounds[9]);
                wait(5);
                gameState = S_BEGIN;
                restart();
                break;
            default:
                lcd.printf("Invalid State");
        }
        handleMenu();
    }
}

void init()
{

    // Set chips opcodes (Dependent on hardware connections)
    opcodes[0] = 0x40;
    opcodes[1] = 0x42;
    opcodes[2] = 0x44;

    /* Create IO Expander objects with their respective opcodes
    * and set port B of each chip for input and port A of each chip
    * for output.
    */

    for(int i = 0; i <3 ; i++) 
    {
        chips[i] = new MCP23S17(spi, p8, opcodes[i]);
        //  Set all 8 Port A bits to output direction
        chips[i]->direction(PORT_A, 0x00);
        //  Set all 8 Port B bits to input direction
        chips[i]->direction(PORT_B, 0xFF);
        // Turn off all LEDs
        chips[i]->write(PORT_A, 0);
    }

    // Clear sequence
    for(int i = 0; i < 15; i++)
        sequence[i] = 0 ;

    set_time(1256729737);  // Set RTC time to Wed, 28 Oct 2009 11:35:37
    
    // Initialize sounds and file system
    char ftotal[] = "/sd/sounds/x.wav";
    for(int i = 0;i<9;i++)
    {
      ftotal[11] = i + '0';
      Sounds[i] = fopen(ftotal, "r");
      
      if(Sounds[i] == NULL)
        lcd.printf("SOUND ERROR");
    }
    
    Sounds[9]  = fopen("/sd/sounds/lose.wav", "r");
    Sounds[10] = fopen("/sd/sounds/win.wav" , "r");
}

int handleMenu()
{
    menuBuffer +=rpg.dir();

    if(menuBuffer == -15) 
    {
        menuState++;
        menuBuffer = 0;
    } else if (menuBuffer == 15) 
    {
        menuState--;
        menuBuffer = 0;
    }

    if(menuState < 0)
        menuState = 0;
    else if(menuState > 2)
        menuState = 2;

    if( oldMenuState != menuState) 
    {
        lcd.cls();
        lcd.printf("Difficulty:");
        lcd.locate(0,1);
        lcd.printf("%s", menuOptions[menuState]);
    }
    oldMenuState = menuState;

    if(rpg.pb())
        return menuState;
    else
        return -1;
}

void playSequence()
{
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Sequence Playing");
    lcd.printf("...");
    wait(delay + 0.5);
    sequence[current] =  time(NULL)%9 ;
    current++;
    for(int i = 0; i < current; i++)
    {
        int chipNum = sequence[i]/3;
        int ledNum  =  sequence[i]%3;
        chips[chipNum]->write(PORT_A, (1 << ledNum) );
        waver.play(Sounds[sequence[i]]);
        rewind(Sounds[sequence[i]]);
        wait(delay);
        chips[chipNum]->write(PORT_A, 0);
        wait(delay);
    }
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("Get ready...");
    wait(timeout + 0.5 );
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("GO!!!");
    wait(delay + 0.3);
}

int listenSequence()
{
    time_t startTime = time(NULL);
    time_t currentTime = startTime;
    time_t timeDiff = 0;
    int totalTime = timeout * current;
    int currentCheck = 0;
    bool correct = false;
    int input;
    int oldInput[3] = {0, 0, 0};
    lcd.cls();
    while(timeDiff <= totalTime)
    {
        lcd.locate(0,0);
        lcd.printf("Time:         %d", totalTime - timeDiff);
        if(totalTime - timeDiff < 10)
        lcd.printf(" ");
        lcd.locate(0,1);
        lcd.printf("Round:        %d",current);
        currentTime = time(NULL);
        timeDiff = currentTime - startTime;
        for(int i = 0; i < 3; i++) 
        {
            // Read lower 3 bits
            input = chips[i]->read(PORT_B) & 7;
            
            if(input != 0 && oldInput[i] == 0)
            {
                chips[i]->write(PORT_A, input);
                wait(0.3);
                chips[i]->write(PORT_A, 0);
                if(correct)
                    return 0;
                
                int rest;
                if(input == 1)
                    rest = 0;
                else if(input == 2)
                    rest = 1;
                else if(input == 4)
                    rest = 2;
                else
                    rest = 3;
                    
                if( i * 3 + rest == sequence[currentCheck])
                {
                     waver.play(Sounds[sequence[currentCheck]]);
                     rewind(Sounds[sequence[currentCheck]]);
                    currentCheck++;
                    correct = true;
                   
                }
                else
                {   lcd.cls();
                    lcd.locate(0,0);
                    lcd.printf("You pressed: %d", i * 3 + rest);
                    lcd.locate(0,1);
                    lcd.printf("Next Was: %d",sequence[currentCheck]);
                    wait(6);
                    return 0; 
                }
            }
            oldInput[i] = input;
            
        }
        correct = false;
        
     if(currentCheck == current)
        break;
    }
    wait(delay + 0.5);
    
    if(currentCheck == current)
       return 1;
    else
       return 0;
}

void restart()
{
    current = 0;
    menuState = 0 ;
    oldMenuState = -1;
}