/**************************************************************************** Module d:\me218\DevProjects\EventFramrwork\EF_SMConveyor1.c Revision 1.0.1 Description This is a Conveyor1 file for implementing state machines under the EF Event Framework. Notes History When Who What/Why -------------- --- -------- 11/07/11 11:26 jec made the queue static 10/30/11 17:59 jec fixed references to CurrentEvent in RunConveyor1SM() 10/23/11 18:20 jec began conversion from SMConveyor1.c (02/20/07 rev) ****************************************************************************/ /*----------------------------- Include Files -----------------------------*/ /* include header files for this state machine as well as any machines at the next lower level in the hierarchy that are sub-machines to this machine */ #include "misc.h" #include "EF_General.h" #include "EF_Queue.h" #include "EF_Events.h" #include "Conveyor1SM.h" /*----------------------------- Module Defines ----------------------------*/ #define QUEUE_SIZE 3 /*---------------------------- Module Functions ---------------------------*/ /* prototypes for private functions for this machine.They should be functions relevant to the behavior of this state machine */ void motorDown1(void); void motorDownFast1(void); void motorUp1(void); void motorStop1(void); void wait(boolean Win); /*---------------------------- Module Variables ---------------------------*/ // everybody needs a state variable, you may need others as well. // type of state variable should match htat of enum in header file static Conveyor1State_t CurrentState; static unsigned char Speed1; static unsigned char topCounter1; static unsigned int GameTimeStart; static unsigned char Fast1; // everybody needs a queue too! static EF_Event Conv1SMQueue[QUEUE_SIZE+1]; /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function InitConveyor1SM Parameters None Returns boolean, False if error in initialization, True otherwise Description Sets up the event queue and does any rother equired initialization for this state machine Notes Author J. Edward Carryer, 10/23/11, 18:55 ****************************************************************************/ boolean InitConveyor1SM ( void ) { unsigned char ucResult1; EF_Event ThisEvent; ucResult1 = EF_InitQueue( Conv1SMQueue, ARRAY_SIZE(Conv1SMQueue) ); if ( ucResult1 == QUEUE_SIZE ) // successful queue init { // put us into the Initial PseudoState CurrentState = InitPState1; // post the initial transition event ThisEvent.EventType = EF_INIT; if (PostConveyor1SM( ThisEvent ) == True) { return True; }else { return False; } }else { return False; } } /**************************************************************************** Function PostConveyor1SM Parameters EF_Event ThisEvent , the event to post to the queue Returns boolean False if the Enqueue operation failed, True otherwise Description Posts an event to the state machine's queue Notes Author J. Edward Carryer, 10/23/11, 19:25 ****************************************************************************/ boolean PostConveyor1SM( EF_Event ThisEvent ) { boolean bResult3; bResult3 = EF_EnQueueFIFO( Conv1SMQueue, ThisEvent ); return bResult3; } /**************************************************************************** Function RunConveyor1SM Parameters void Returns boolean, Flase if an error encountered, True otherwise Description add your description here Notes uses nested switch/case to implement the machine. Author J. Edward Carryer, 10/23/11, 18:38 ****************************************************************************/ boolean RunConveyor1SM( void ) { EF_Event ThisEvent; Conveyor1State_t NextState; static boolean WinState = False; // pull an event from the queue ThisEvent = EF_DeQueue( Conv1SMQueue ); // we should only call the Run function if we know that there is something in // the queue, so if we found EF_NO_EVENT something is wrong if (ThisEvent.EventType == EF_NO_EVENT ) { return False; }else { switch ( CurrentState ) { case InitPState1 : // If current state is initial Pseudo State if ( ThisEvent.EventType == EF_INIT )// only respond to EF_Init { // now put the machine into the actual initial state NextState = InitConveyor1; } break; case InitConveyor1 : //display ready NextState = InitConveyor1; if (ThisEvent.EventType == EF_StartButton) { // start up the game - set speeds, game time, control LEDs, and set motors. Speed1 = SetDifficulty(); Fast1 = SetDifficultyFast(); NextState = DownNormal1; PTT |= LED_ON; WinState = False; motorDown1(); topCounter1 = 0; GameTimeStart = EF_Timer_GetTime(); } break; case DownNormal1 : // monkey is above halfway point, only accepts user interaction of shot. otherwise, crossing threshold, end of game (time or bottom), or restarting game will cause a change of state NextState = DownNormal1; switch(ThisEvent.EventType) { case EF_Shot1 : NextState = Paused1; motorStop1(); EF_Timer_InitTimer(2, PAUSE); break; case EF_EndGameTime : NextState = WinGame1; motorStop1(); ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); break; case EF_Middle1 : NextState = DownFast1; printf("\r\n middle switch"); motorDownFast1(); printf("\r\n motor speeds up"); break; case EF_MonkeyBottom : NextState = LoseGame1; motorStop1(); ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); printf("\r\n monkey bottom"); break; case EF_StartButton : NextState = EndGame1; motorStop1(); ThisEvent.EventType = EF_GameOver; EF_PostList00(ThisEvent); printf("\r\n reset game"); break; } break; case DownFast1 : // monkey is past halfway point, only accepts user interaction of wave. otherwise, end of game (time or bottom), or restarting game will cause a change of state NextState = DownFast1; switch(ThisEvent.EventType) { case EF_Wave1 : NextState = ClimbingUp1; EF_Timer_InitTimer(2, CLIMB); motorUp1(); printf("\r\n Wave 1"); break; case EF_EndGameTime : NextState = WinGame1; motorStop1(); ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); printf("\r\n end game timer"); break; case EF_MonkeyBottom : NextState = LoseGame1; motorStop1(); ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); printf("\r\n monkey bottom"); break; case EF_StartButton : NextState = EndGame1; motorStop1(); ThisEvent.EventType = EF_GameOver; EF_PostList00(ThisEvent); printf("\r\n reset game "); break; } break; case Paused1 : // waits for timeout from EF_Timer(shot) to occur before restarting motor NextState = Paused1; switch(ThisEvent.EventType) { case EF_TIMEOUT : NextState = DownNormal1; motorDown1(); printf("\r\n done pause 1"); break; case EF_EndGameTime : NextState = WinGame1; motorStop1(); ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); printf("\r\n end game timer"); break; case EF_MonkeyBottom : NextState = LoseGame1; motorStop1(); ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); printf("\r\n monkey bottom"); break; case EF_Middle1 : NextState = DownFast1; printf("\r\n middle switch"); motorDownFast1(); break; case EF_StartButton : NextState = EndGame1; motorStop1(); ThisEvent.EventType = EF_GameOver; EF_PostList00(ThisEvent); printf("\r\n reset game"); break; } break; case ClimbingUp1 : // waits for timeout from EF_Timer(wave) or triggered top limit switch (of own SM) before reversing motor NextState = ClimbingUp1; switch(ThisEvent.EventType) { case EF_TIMEOUT : NextState = DownNormal1; motorDown1(); printf("\r\n done climb 1"); break; case EF_TopLimit1 : NextState = DownNormal1; printf("\r\n top climb 1"); motorDown1(); break; case EF_EndGameTime : NextState = WinGame1; ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); motorStop1(); printf("\r\n end game timer"); break; case EF_MonkeyBottom : NextState = LoseGame1; ThisEvent.EventType = EF_WinLose; EF_PostList01(ThisEvent); motorStop1(); printf("\r\n monkey bottom"); break; case EF_StartButton : NextState = EndGame1; motorStop1(); ThisEvent.EventType = EF_GameOver; EF_PostList00(ThisEvent); printf("\r\n reset game"); break; } break; case WinGame1 : // if game time expired, display win. SM1 is last on run order, so all SMs have stopped their motors by the time this code is executed. as such, no action is taking place when the win is displayed motorStop1(); printf("\r\n won game"); WinState = True; wait(WinState); ThisEvent.EventType = EF_GameOver; EF_PostList00(ThisEvent); NextState = EndGame1; break; case LoseGame1 : //if monkey hits bottom, let monkeys stay in position for a paused time to show that user has lost. motorStop1(); GameTimeStart = 0; printf("\r\n lost game"); wait(WinState); //display lose ThisEvent.EventType = EF_GameOver; EF_PostList00(ThisEvent); NextState = EndGame1; break; case EndGame1 : // begin process of reseting motors to top position motorUp1(); GameTimeStart = 0; printf("\r\n end game 1"); NextState = EndGame1; if (ThisEvent.EventType == EF_TopLimit1) { motorStop1(); NextState = ResetGame1; } break; case ResetGame1 : // this state machine's monkey is in top position. wait till all monkeys are reset before returning to init NextState = ResetGame1; GameTimeStart = 0; if (ThisEvent.EventType == EF_ResetComplete) { NextState = InitConveyor1; } break; } //end state case structure CurrentState = NextState; return True; } //end else } //end run function /**************************************************************************** Function IsConveyor1SMQEmpty Parameters void Returns boolean True if the Queue is empty, False if the queue has something in it Description tests if this state machine's queue is empty Notes Author J. Edward Carryer, 10/23/11, 19:28 ****************************************************************************/ boolean IsConveyor1SMQEmpty( void ){ return EF_IsQueueEmpty( Conv1SMQueue ); } /**************************************************************************** Function QueryConveyor1SM Parameters None Returns Conveyor1State_t The current state of the Conveyor1 state machine Description returns the current state of the Conveyor1 state machine Notes Author J. Edward Carryer, 10/23/11, 19:21 ****************************************************************************/ Conveyor1State_t QueryConveyor1SM ( void ) { return(CurrentState); } /*************************************************************************** private functions ***************************************************************************/ void motorDown1(void) { if (MOTOR1 != MOTOR1_DOWN) { PTM |= MOTOR1_DOWN; //ensure motor travelling in correct direction } PWMS12_SetDuty(Speed1, PWMS12_CHAN0 ); //set speed via PWM } void motorDownFast1(void) { if (MOTOR1 != MOTOR1_DOWN) { PTM |= MOTOR1_DOWN; //ensure motor travelling in correct direction } PWMS12_SetDuty(Fast1, PWMS12_CHAN0 ); //set speed via PWM } void motorUp1(void) { if (MOTOR1 != 0) { PTM &= MOTOR1_UP; //reverse motor direction } PWMS12_SetDuty(40, PWMS12_CHAN0); //set speed } void motorStop1(void) { if (MOTOR1 != MOTOR1_DOWN) { PTM |= MOTOR1_DOWN; } PWMS12_SetDuty(0, PWMS12_CHAN0); //stop motor } unsigned char SetDifficulty(void) { unsigned char speed; if (ADS12_ReadADPin(0) > UPPER_LIM) //if threshold in bananas { speed = 45; } else if ((ADS12_ReadADPin(0) <= UPPER_LIM) && (ADS12_ReadADPin(0) >= LOWER_LIM)) //if threshold in medium { speed= 37; } else // if threshold in easy { speed = 30; } return speed; } // once past the middle of the tree, the monkeys travel faster. We had to set these pwm values after testing some speeds, so rather than making a linear increment, we made two separate functions unsigned char SetDifficultyFast(void) { unsigned char speed; if (ADS12_ReadADPin(0) > UPPER_LIM) { speed = 57; } else if ((ADS12_ReadADPin(0) <= UPPER_LIM) && (ADS12_ReadADPin(0) >= LOWER_LIM)) { speed= 52; } else { speed = 40; } return speed; } //protect game time variable unsigned int GameTime(void) { return GameTimeStart; } // this function controls for the LEDs for displaying a win // it uses blocking code in order to stop the other SM motors from resetting or from the user attempting to reset the game. void wait(boolean Win) { unsigned int InitTime = EF_Timer_GetTime(); unsigned int StrobeTime; while( (EF_Timer_GetTime() - InitTime) < END_TIME ) { if (Win == True) { PTAD |= WIN_ON; StrobeTime = EF_Timer_GetTime(); PTT &= LED_OFF; printf("\r\n LED off"); while(EF_Timer_GetTime() - StrobeTime < END_TIME/10); StrobeTime = EF_Timer_GetTime(); PTT |= LED_ON; printf("\r\n LED on"); while(EF_Timer_GetTime() - StrobeTime < END_TIME/10); } else { PTT &= LED_OFF; PTAD &= WIN_OFF; } } PTT &= LED_OFF; PTAD &= WIN_OFF; }