/***************************************************************************
Team Firefox
ME 218A
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) {};
}