/**************************************************************************** Module Meteor_SM.c Revision 1.0.1 Description This is the meteor service under the Gen2 Events and Services Framework. Notes ****************************************************************************/ /*----------------------------- Include Files -----------------------------*/ /* include header files for this service */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include "Meteor_SM.h" #include <string.h> #include "Meteor.h" #include "Cannon.h" #include "Cannon_SM.h" #include "ArcadeFSM.h" /* include header files for hardware access */ #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_sysctl.h" /* include header files for the framework */ #include "ES_Configure.h" #include "ES_Framework.h" #include "ES_DeferRecall.h" #include "ES_ShortTimer.h" /*----------------------------- Module Defines ----------------------------*/ // these times assume a 1.000mS/tick timing #define ONE_SEC 1000 #define HALF_SEC (ONE_SEC/2) #define TWO_SEC (ONE_SEC*2) #define FIVE_SEC (ONE_SEC*5) #define DESTROYED_DELAY 100 #define FALL_TIME 1000-(150*(MachineCounter-1)) #define BLINK_COUNT_MAX 7 //Percentage error allowance (on one side) for cannon localization #define ERROR 5 #define MAX_COUNT 8 /*---------------------------- Module Functions ---------------------------*/ /* prototypes for private functions for this service.They should be functions relevant to the behavior of this service */ static uint8_t RandomNext(void); static uint8_t GetStartingBank(void); /*---------------------------- Module Variables ---------------------------*/ // with the introduction of Gen2, we need a module level Priority variable static uint8_t MyPriority; static Meteor_SMState_t CurrentSMState; static uint16_t counter = 0; static uint8_t BankNum = 3; //Initialize to an invalid LED bank static uint8_t blinkcount = 0; static uint8_t MachineCounter = 0; // add a deferral queue for up to 3 pending deferrals +1 to allow for overhead static ES_Event_t DeferralQueue[3+1]; /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function InitMeteor_SM Parameters uint8_t : the priorty of this service Returns bool, false if error in initialization, true otherwise Description Saves away the priority, and does any other required initialization for this service Notes Author Trey Weber ****************************************************************************/ bool InitMeteor_SM ( uint8_t Priority ) { MyPriority = Priority; //Initialize meteor hardware Meteor_HWInit(); //Set SM currentstate CurrentSMState = Idle_M; return true; } /**************************************************************************** Function PostMeteor_SM Parameters EF_Event ThisEvent ,the event to post to the queue Returns bool false if the Enqueue operation failed, true otherwise Description Posts an event to this state machine's queue Notes Author Trey Weber ****************************************************************************/ bool PostMeteor_SM( ES_Event_t ThisEvent ) { return ES_PostToService( MyPriority, ThisEvent); } /**************************************************************************** Function RunMeteor_SM Parameters ES_Event_t : the event to process Returns ES_Event_t, ES_NO_EVENT if no error ES_ERROR otherwise Description add your description here Notes Author Trey Weber ****************************************************************************/ ES_Event_t RunMeteor_SM( ES_Event_t ThisEvent ) { ES_Event_t NewEvent; ES_Event_t ReturnEvent; ReturnEvent.EventType = ES_NO_EVENT; switch (CurrentSMState) { case Idle_M: //If event is begin meteor interaction if (ThisEvent.EventType == Meteor) { //Reset count counter = 0; //Init timer ES_Timer_InitTimer(METEOR_TIMER, FALL_TIME); //Get "random" number if(MachineCounter == 0) { //BankNum = ES_Timer_GetTime() % 3; BankNum = GetStartingBank(); } else { BankNum = RandomNext(); } //Turn on top LED of bank Meteor_LightLEDBank(BankNum, counter + 1); //Update current state CurrentSMState = MeteorFalling; //Increment Machine counter MachineCounter++; } else if(ThisEvent.EventType == End_Of_Game || ThisEvent.EventType == RST) { MachineCounter = 0; } break; case MeteorFalling: //Check for reset or end of game event if (ThisEvent.EventType == RST || ThisEvent.EventType == End_Of_Game) { //Update current state CurrentSMState = Idle_M; //Reset counter counter = 0; //Clear all LEDs Meteor_ClearAll(); //Reset BankNum BankNum = 3; } //else if cannon button down else if (ThisEvent.EventType == Cannon_Button_Down) { //Check guard condition, meteor in range uint8_t CannonPos = QueryCannonPosition(); //Get bank % position value uint8_t BankValue = QueryBankPositions(BankNum); if ((CannonPos < BankValue + ERROR) && (CannonPos > BankValue - ERROR)) { //Post meteor destroyed to Meteor SM and cannon SM ThisEvent.EventType = Meteor_Destroyed; PostCannon_SM(ThisEvent); PostMeteor_SM(ThisEvent); } } //else if we get a timeout event else if (ThisEvent.EventType == ES_TIMEOUT) { //If counter is less than max if (counter < MAX_COUNT) { //Increment counter counter++; //Decrement LED Meteor_LightLEDBank(BankNum, counter + 1); //Init timer ES_Timer_InitTimer(METEOR_TIMER, FALL_TIME); } //else we have reached max count else { //Reset counter counter = 0; //Reset BankNum to invalid number //BankNum = 3; //Update state CurrentSMState = Idle_M; //Clear LEDs Meteor_ClearAll(); //Post end of game (game over) NewEvent.EventType = End_Of_Game; NewEvent.EventParam = GAME_OVER; ES_PostAll(NewEvent); } } //Else if meteor is destroyed else if (ThisEvent.EventType == Meteor_Destroyed) { //Reset counter //counter = 0; //Update state CurrentSMState = MeteorFlashing; //CurrentSMState = Idle_M; ES_Timer_InitTimer(METEOR_TIMER, DESTROYED_DELAY); Meteor_LightLEDBank(BankNum, counter + 1); //Clear all LEDs //Meteor_ClearAll(); //Reset BankNum to invalid number //BankNum = 3; //Post interaction complete to Arcade SM } break; case MeteorFlashing: if (ThisEvent.EventType == ES_TIMEOUT) { if (blinkcount <= BLINK_COUNT_MAX) { //we are still flashing if ((blinkcount % 2) == 0) { //turn off Meteor_LightLEDBank(BankNum, 0); } else { //turn on Meteor_LightLEDBank(BankNum, counter + 1); } blinkcount++; ES_Timer_InitTimer(METEOR_TIMER, DESTROYED_DELAY); } else { //we are done flashing //Reset counter counter = 0; blinkcount = 0; //Update state CurrentSMState = Idle_M; Meteor_ClearAll(); //Reset BankNum to invalid number //BankNum = 3; NewEvent.EventType = Interaction_Completed; PostArcadeFSM(NewEvent); } } break; } return ReturnEvent; } /*************************************************************************** private functions ***************************************************************************/ /*** RandomNext Function Description Arguments: none Returns: uint8_t, random number This function generates a pseudorandom number Author: Riyaz Merchant ***/ static uint8_t RandomNext(void) { uint8_t ReturnVal = 0xFF; //intialize //Get System time uint16_t SysTime = ES_Timer_GetTime(); // See if value is odd or even uint8_t odd = SysTime%2; //Make decision about next bank num based current bankNum switch (BankNum) { case 0: { if(odd) { ReturnVal = 1; } else { ReturnVal = 2; } break; } case 1: { if(odd) { ReturnVal = 0; } else { ReturnVal = 2; } break; } case 2: { if(odd) { ReturnVal = 0; } else { ReturnVal = 1; } break; } } //Return value return(ReturnVal); } static uint8_t GetStartingBank(void) { //Get current cannon position uint8_t CannonPos = QueryCannonPosition(); //find the distance from each bank uint8_t Distances [3] = {0,0,0}; int8_t index, diff; for(index = 0; index < 3; index++) { diff = (int8_t)(CannonPos - QueryBankPositions(index)); Distances[index] = abs(diff); } //find the maximum distance uint8_t MaxLoc = 0; //Start loop, run 2 times for(index = 0; index<2; index++) { //compare n+1 to n //if n+1 bigger, set max to n+1 if(Distances[index+1] > Distances[index]) { MaxLoc = index + 1; } //End if } //End loop //Return bank that is the farthest return(MaxLoc); } /*------------------------------- Footnotes -------------------------------*/ /*------------------------------ End of file ------------------------------*/