Está en la página 1de 7

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

Module
ReloadStateMachine.c

****************************************************************************/
/*----------------------------- Include Files -----------------------------*/
// Basic includes for a program using the Events and Services Framework
#include "ES_Configure.h"
#include "ES_Framework.h"

/* 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 "ReloadStateMachine.h"
#include "ReloadIRCaptureModule.h"
#include "MyPWMLib.h"
#include "MasterSM.h"

/*----------------------------- Module Defines ----------------------------*/


// define constants for the states for this machine
// and any other local defines

#define ENTRY_STATE EMIT_IR


#define RELOAD_TIMEOUT_MS (2000)
#define BALL_TIMEOUT (2000)
#define NUM_PWM (6)
#define PWM_CHANNEL (10)
//TODO TAKE ABOVE OUT!

/*---------------------------- Module Functions ---------------------------*/


/* prototypes for private functions for this machine, things like during
functions, entry & exit functions.They should be functions relevant to the
behavior of this state machine
*/
static ES_Event_t DuringMeasuringState(ES_Event_t Event);
static ES_Event_t DuringWaitingState(ES_Event_t Event);
static ES_Event_t DuringEmitIR(ES_Event_t Event);
/*---------------------------- Module Variables ---------------------------*/
// everybody needs a state variable, you may need others as well
static ReloadState_t CurrentState;
static int CurrentPeriod_US;
static bool HeadedToDefense = false;

/*------------------------------ Module Code ------------------------------*/


/****************************************************************************
Function
RunTemplateSM

Parameters
ES_Event_t: the event to process

Returns
ES_Event_t: an event to return

Description
add your description here
Notes
uses nested switch/case to implement the machine.
Author
J. Edward Carryer, 2/11/05, 10:45AM
****************************************************************************/
ES_Event_t RunReloadStateMachine(ES_Event_t CurrentEvent)
{
//printf("running reload state machine \r\n");
bool MakeTransition = false;/* are we making a state transition? */
ReloadState_t NextState = CurrentState;
ES_Event_t EntryEventKind = { ES_ENTRY, 0 }; // default to normal entry to new
state
ES_Event_t ReturnEvent = CurrentEvent; // assume we are not consuming
event

switch (CurrentState)
{
//Entry state is measuring period.
case EMIT_IR:
{
//if we enter, then we need to start pulsing IR
//if we exit, then we disable pulsing
ReturnEvent = CurrentEvent = DuringEmitIR(CurrentEvent);

if (CurrentEvent.EventType != ES_NO_EVENT)
{
switch (CurrentEvent.EventType)
{
//if we got an event from the break-beam service
case GOT_BALL:
{
// we are leaving reload state machine and going to shoot state machine
//let upper state machine know we got a ball!
//TODO: make sure we increment ball count in upper state machine!
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
IncrementNumBalls();
printf("Got ball event found! \r\n");
}
break;
case ES_TIMEOUT:
{
//if the reload timer timesout, we go back to measuring IR period.
if (CurrentEvent.EventParam == RELOAD_TIMER)
{
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
IncrementNumBalls();
printf("Got ball event found! \r\n");
}
}
break;
//if we are entering first offense, then move to waiting for ball.
// this ensures we go shoot instead of trying to reload again (as we have
a ball)
case FIRST_OFFENSE:
{
//we need to measure period again
NextState = WAITING_FOR_BALL;
MakeTransition = true; //mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got first offense event! \r\n");
}
break;

case OFFENSE_STARTED:
{
//we need to measure period again
NextState = WAITING_FOR_BALL;
MakeTransition = true; //mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got offense (not first while in reloading state machine.) event!
\r\n");
}
break;

case DEFENSE_STARTED:
{
//we need to measure period again
NextState = WAITING_FOR_BALL;
MakeTransition = true;
HeadedToDefense = true;
//mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got offense (not first while in reloading state machine.) event!
\r\n");
}
break;
}
}
}
break;

//state is measuring period.


case MEASURING_PERIOD:
{
//if we enter, then we enable interrupts coming from receive
//if we exit, then we disable interrupts
ReturnEvent = CurrentEvent = DuringMeasuringState(CurrentEvent);
if (CurrentEvent.EventType != ES_NO_EVENT)
{
switch (CurrentEvent.EventType)
{
//if our ISR tells us we found the period
case FOUND_RELOAD_IR:
{
printf("running measuring period and got found reload ir %d \r\n",
CurrentEvent.EventParam);
//set current period
EntryEventKind.EventParam = CurrentEvent.EventParam;
// move to waiting for ball
//note that upon entering waiting for ball, we will start emitting IR
pulses at the appropriate peiod.
NextState = EMIT_IR;
MakeTransition = true;
//upper state machine shouldn't care about this.
ReturnEvent.EventType = ES_NO_EVENT;
}
break;
}
}
}
break;

case WAITING_FOR_BALL:
{
//if we are waiting for ball
// upon entering: start pulsing pwm.
ReturnEvent = CurrentEvent = DuringWaitingState(CurrentEvent);

if (CurrentEvent.EventType != ES_NO_EVENT)
{
switch (CurrentEvent.EventType)
{
//If our ball-break IR posts an event
case GOT_BALL:
{
//increment num balls
IncrementNumBalls();
// tell main state machine we got a ball.
if (HeadedToDefense)
{
ReturnEvent.EventType = DEFENSE_STARTED;
HeadedToDefense = false;
}
else
{
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
}
}
break;
//if our ball waiting times out, then we just go try to shoot
case ES_TIMEOUT:
{
IncrementNumBalls();
//make sure it's from the right timer.
if (CurrentEvent.EventParam == BALL_TIMER)
{
// tell main state machine we got a ball.
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
if (HeadedToDefense)
{
ReturnEvent.EventType = DEFENSE_STARTED;
HeadedToDefense = false;
}
else
{
ReturnEvent.EventType = READY_TO_NAV_TO_SHOOT;
}
}
}
case OFFENSE_STARTED:
{
HeadedToDefense = false;
}
break;
case DEFENSE_STARTED:
{
//we need to measure period again
HeadedToDefense = true;
//mark that we are taking a transition
// the upper state machine should not care about this.
ReturnEvent.EventType = ES_NO_EVENT;
printf("Got offense (not first while in reloading state machine.) event!
\r\n");
}
break;
}
}
}
break;
}
// If we are making a state transition
if (MakeTransition == true)
{
// Execute exit function for current state
CurrentEvent.EventType = ES_EXIT;
RunReloadStateMachine(CurrentEvent);
CurrentState = NextState; //Modify state variable

// Execute entry function for new state


// this defaults to ES_ENTRY
RunReloadStateMachine(EntryEventKind);
}
return ReturnEvent;
}

/****************************************************************************
Function
StartTemplateSM

Parameters
None

Returns
None

Description
Does any required initialization for this state machine
Notes

Author
J. Edward Carryer, 2/18/99, 10:38AM
****************************************************************************/
void StartReloadStateMachine(ES_Event_t CurrentEvent)
{
if (CurrentEvent.EventType != ES_ENTRY)
{
printf("Warnign, reload state ,machine was starting with a non-entry
event\r\n");
}
printf("reloading state machine started and emitting at half of %d us\r\n",
CurrentEvent.EventParam);
// to implement entry to a history state or directly to a substate
// you can modify the initialization of the CurrentState variable
// otherwise just start in the entry state every time the state machine
// is started
if (ES_ENTRY_HISTORY != CurrentEvent.EventType)
{
CurrentState = ENTRY_STATE;
}
// call the entry function (if any) for the ENTRY_STATE
RunReloadStateMachine(CurrentEvent);
}

/****************************************************************************
Function
QueryTemplateSM

Parameters
None

Returns
TemplateState_t The current state of the Template state machine

Description
returns the current state of the Template state machine
Notes

Author
J. Edward Carryer, 2/11/05, 10:38AM
****************************************************************************/
ReloadState_t QueryReloadStateMachine(void)
{
return CurrentState;
}

/***************************************************************************
private functions
***************************************************************************/

static ES_Event_t DuringEmitIR(ES_Event_t Event)


{
ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption

// process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events


if ((Event.EventType == ES_ENTRY) ||
(Event.EventType == ES_ENTRY_HISTORY))
{
// set period
CurrentPeriod_US = Event.EventParam;
//start timer for reload timeout
ES_Timer_InitTimer(RELOAD_TIMER, RELOAD_TIMEOUT_MS);

if (CurrentPeriod_US != 0)
{
My_PWM_SetFreq(2000000 / CurrentPeriod_US, 5);
My_PWM_SetDuty(50, PWM_CHANNEL);
printf("freq = %d\r\n", 2000000 / CurrentPeriod_US);
}
}
else if (Event.EventType == ES_EXIT)
{
My_PWM_SetDuty(0, PWM_CHANNEL);
ES_Timer_StopTimer(RELOAD_TIMER);
}
else
//nothing to do here.
{}
// return either Event, if you don't want to allow the lower level machine
// to remap the current event, or ReturnEvent if you do want to allow it.
return ReturnEvent;
}

static ES_Event_t DuringMeasuringState(ES_Event_t Event)


{
ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption

// process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events


if ((Event.EventType == ES_ENTRY) ||
(Event.EventType == ES_ENTRY_HISTORY))
{
// implement any entry actions required for this state machine
CurrentPeriod_US = 0;
//enable interrupts
EnableReloadIR();
}
else if (Event.EventType == ES_EXIT)
{
//deacticve interrupts for reload ir
DisableReloadIR();
ES_Timer_InitTimer(RELOAD_TIMER, RELOAD_TIMEOUT_MS);
}
else
// nothing here
{}
return ReturnEvent;
}

static ES_Event_t DuringWaitingState(ES_Event_t Event)


{
ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption

// process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events


if ((Event.EventType == ES_ENTRY) ||
(Event.EventType == ES_ENTRY_HISTORY))
{
// implement any entry actions required for this state machine
//Start Ball Timer
ES_Timer_InitTimer(BALL_TIMER, BALL_TIMEOUT);
}
else if (Event.EventType == ES_EXIT)
{
//when we exit, we'll simply pass event up.
ES_Timer_StopTimer(BALL_TIMER);
}
else
//we're just sitting and waiting, so don't do anything
{}

return ReturnEvent;
}

También podría gustarte