/***************************************************************************

Main for FLICKER (aaaProjectMain.c)

Mission Impossible Flicker

Team Firefox

ME 218A 11/20/09

This software module runs the flicker at a high level

****************************************************************************/

#include <timers12.h>

#include <stdio.h>

#include <ME218_C32.h>

 

#include "StepperMotor.h"

#include "Download.h"

#include "LEDMap.h"

#include "IR.h"

#include "Flicker.h"

#include "Stage_LEDs.h"

#include "Music.h"

 

//Flicker is run as a state machine with the following states:

typedef enum {  IDLE,

                IR,

                GRAPPLE,

                DOWNLOAD,

                FAIL,

                SUCCESS,

                RESET_SHOW

  } STATE_t;

               

//This function is used to coordinate timing between FLICKER and MP3 player at power up

void wait(unsigned int);

 

//Calibrations

static unsigned int SuccessTime = 8000;         //Time to show success display in ms

static unsigned int FailTime = 3000;            //Time to show fail display in ms

 

void main() {

      STATE_t myState;     //Current state

      STATE_t dummyState; //Used to prevent switching states within one while loop iteration

     

      static char isAlerted;             //Indicates weather user made Tom hit the floor

 

      static unsigned int finaleTime;    //Timing variables for the fail and success displays

      static unsigned int myTime;        //Timing variable

     

      FLICKER_EVENT_t myFlickerEvent;    //Event variables for each event driven module

      MOTOR_STATUS_t myMotorStatus;

      DOWNLOAD_EVENT_t myDLEvent;

      LEDMap_Status_t myLEDMapStatus;

      IR_STATUS_t myIRStatus;

     

      static char waitingOnIRActive;     //Used in case IR beam misreads on new game; forces user

                                         //break the IR beam a few times before continuing onto next

                                         //stage

      

      //set 1 [ms] clock for use by all modules

      TMRS12_Init(TMRS12_RATE_1MS);

     

      //set I/O pins

      DDRM = 0x3C;

      DDRT = 0xFE;

      ADS12_Init("OOOOOOOA");

     

      //MP3 player takes a few seconds to boot up on power up; delay FLICKER by 2 sec to ensure MP3   

      //player is ready to accept button push commands

      wait(2000);

     

      //Intialize modules (can be blocking)

      initStepMotor(100);  //Ram Tom Cruise into stop for 100 steps to ensure correct zero position

//on stepper motor

      initDownload();

      initLEDMap();

      initFlicker();

      initMusic();

      myState = IDLE;

     

      while(1) {

        //run state specific code

        dummyState = myState;

        switch (dummyState) {

          case IDLE:

              //Set indicator LEDs

              turnOnActive(0);                  //Turn off ultra-bright white LEDs

              turnOnFail(0);                    //Turn off red LEDs

              activateStage(STAGE_IDLE);        //Turn off all stage indicator LEDs

 

              //Check for active signal from forced start button or opto-iso

              myFlickerEvent = checkFlickerEvents();

              if (myFlickerEvent == FLICKER_START) {

                startLEDMap();                                //Start LED Guard map

                myIRStatus = checkIRStatus();                 //Check if IR beam is already broken

                                                              //(which shouldn’t happen)

                if (myIRStatus == IR_BROKEN_STATUS) {

                  waitingOnIRActive = 1;                      //Make note that IR beam already broken

                }

                else {

                  waitingOnIRActive = 0;                      //IR beam is reading fine

                }

                myState = IR;                                 //Move on to next state

                break;

              }

              break;

         

          case IR:

              //Play Mission Impossible music

              playMusic();

             

              //Set indicator LEDs

              turnOnActive(0);

              turnOnFail(1);

              activateStage(STAGE_IR);

             

              //Check if guard has arrived (meaning user failed)

              myLEDMapStatus = checkLEDMapEvents();

              if (myLEDMapStatus == LEDMap_GUARD_ARRIVED) {

                myState = FAIL;                         //Move on to fail state

                finaleTime = TMRS12_GetTime();          //Record the start time of the fail display

                break;

              }

             

//Check if IR beam is broken (if so, move on to next stage as long as IR beam is

//reading correctly)

              myIRStatus = checkIRStatus();

              if (myIRStatus == IR_BROKEN_STATUS) {

                if (!waitingOnIRActive) {

                  myState = GRAPPLE;            //Move on to next stage

                   isAlerted = 0;               //Indicates that the alarm hasn’t been tripped

                  break;

                }

              }

              else {

                waitingOnIRActive = 0;   //IR beam is reading fine, no need to wait for a change in

                                         //the signal

              }

              break;

         

          case GRAPPLE:

              //Set indicator LEDs

              if (isAlerted) {           //If the alarm is tripped, blink lights

                blinkFail(150);

                blinkActive(250);

              }

              else { 

                turnOnActive(1);

                turnOnFail(0);

              }

              activateStage(STAGE_GRAPPLE);

             

//Check if guard has arrived (meaning user failed)

              myLEDMapStatus = checkLEDMapEvents();

              if (myLEDMapStatus == LEDMap_GUARD_ARRIVED) {

                myState = FAIL;                 //Move on to fail state

                finaleTime = TMRS12_GetTime();  //Record the start time of the fail display

                break;

              }

             

              //Allow user to run the motor using the grapple control dial

              myMotorStatus = checkStepMotorStatus();

              if (myMotorStatus == MOTOR_NOT_IN_RANGE_STATUS) {

                   resetDownload();      //If Tom is not in range of the computer reset the download

//(this also causes the download progress LEDs to turn off)

              }

              if (myMotorStatus == MOTOR_IN_RANGE_STATUS) {

                    //Check if the download has been started as a result of the user inserting the

      //disk

                   myDLEvent = checkDownloadEvents();

                   if (myDLEvent == DOWNLOAD_STARTED_EVENT){

                      myState = DOWNLOAD;       //Move on to next state

                      clearDownloadDisplay();   //Make sure all progress LEDs turn off (could still

                                                //be on from blinking)

                      break;

                   }

              }

              if (myMotorStatus == MOTOR_HIT_FLOOR_STATUS) {

                    //If user hits the floor, not an automatic fail, just speed up guard map and 

      //flash floor and ceiling lights

      LEDMapGuardAlerted();

                   isAlerted = 1;        //Indicates that the floor and ceiling lights should be

//blinked

              }

              break;

             

          case DOWNLOAD:

              //Set indicator LEDs

              if (isAlerted) {           //If the alarm is tripped, flash lights

                blinkFail(150);

                blinkActive(250);

              }

              else { 

                turnOnActive(1);

                turnOnFail(0);

              }

              activateStage(STAGE_DOWNLOAD);    //Turn on the correct stage indicator LED

             

//Check if guard has arrived (meaning user failed)

              myLEDMapStatus = checkLEDMapEvents();

              if (myLEDMapStatus == LEDMap_GUARD_ARRIVED) {

                myState = FAIL;                 //Move on to fail state

                finaleTime = TMRS12_GetTime();  //Record the start time of the fail display

                break;

              }

              

              //Check if download has completed

              myDLEvent = checkDownloadEvents();

              if ((myDLEvent == DOWNLOAD_COMPLETE_EVENT) && (!isDiskIn())){ //User must eject disk

                                                                            //after download has

                                                                            //completed

                restartMusic();                 //Start MI theme over again

                myState = SUCCESS;              //Move on to success state

                resetDownload();                //Clear the download progress LEDs

                finaleTime = TMRS12_GetTime();  //Record the start time of the success display

                break;

              }

             

              break;

             

          case FAIL:

              stopMusic();

              myTime = TMRS12_GetTime();

              blinkFail(150);                   //Blink the red LEDs

              turnOnActive(0);                  //Turn off the ultra-bright white LEDs

             

              //Check if enough time has passed for the fail display to be over

              if ((myTime - finaleTime) > FailTime) {

                startNextFlicker();            //Signal next flicker to start

                myState = RESET_SHOW;          //Move on to state that resets the FLICKER

              }

              break;

         

          case SUCCESS:

              slowVictoryReset();               //Slowly raise Tom Cruise back to start position

              myTime = TMRS12_GetTime();

              blinkActive(150);                 //Blink ultra-bright white LEDs

              turnOnFail(0);                    //Turn off Red LEDs

             

              //Check if enough time has passed for the success display to be over

              if ((myTime - finaleTime) > SuccessTime) {

                stopMusic();             //Stop the music

                startNextFlicker();      //Signal next flicker to start

                myState = RESET_SHOW;    // Move on to state that resets the FLICKER

              }

              break;

             

          case RESET_SHOW:

              initLEDMap();        //Reset guard map

              resetStage();        //Turn off all stage indicator LEDs

              resetDownload();    //Turn off all the download progress LEDs

              turnOnActive(0);    //Turn off the ultra-bright white LEDs

              turnOnFail(0);      //Turn off the red LEDs

              //Make sure the motor is back in the start position

 do {

                myMotorStatus = resetStepMotorStatus();

              } while (myMotorStatus == MOTOR_RESETTING_STATUS);

              initStepMotor(50);  //Ram Tom Cruise into the stop for 50 steps to reset the stepper

//motor position

              myState = IDLE;     //Move to the idle state where the flicker will wait to be

//restarted

              break;

        }     

      }

}

 

//delay for a specified number of ms

static void wait(unsigned int ms) {

  unsigned int myTime = 0;

  myTime = TMRS12_GetTime();

  //wait until the current time minus the start time is greater than the wait time

  while ((TMRS12_GetTime() - myTime) < ms) {};

}