Sei sulla pagina 1di 10

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

Module
Car.c

Revision
1.0.1

Description
This is a file for implementing car flat state machines under the
Gen2 Events and Services Framework.

Notes

History
When Who What/Why
-------------- --- --------
01/15/12 11:12 jec revisions for Gen2 framework
11/07/11 11:26 jec made the queue static
10/30/11 17:59 jec fixed references to CurrentEvent in RunTemplateSM()
10/23/11 18:20 jec began conversion from SMTemplate.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 "ES_Configure.h"
#include "ES_Framework.h"
#include "Car.h"
#include "PWM16Tiva.h"
// the headers to access the GPIO subsystem
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"

// the headers to access the TivaWare Library


#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"

#include "BITDEFS.H"

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

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


/* prototypes for private functions for this machine.They should be functions
relevant to the behavior of this state machine
*/

void Car_Init(void);

void Car_Forward(void);
void Car_Reverse(void);
void Car_Stop(void);

/*---------------------------- 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

// with the introduction of Gen2, we need a module level Priority var as well
static uint8_t MyPriority;
static uint8_t LastInput_CarPlace;
static uint8_t LastInput_LimitHome;
static uint8_t LastInput_LimitEnd;
static uint8_t ResetEarly = 0;

static CarState_t CurrentState;

#define PWM_DUTY_CYCLE 30
#define PWM_DUTY_CYCLE_REVERSE 30
#define PWM_FREQ 100

#define CAR_FORWARD_TIME 390


/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
Function
InitCar

Parameters
uint8_t : the priorty of this service

Returns
bool, false if error in initialization, true otherwise

Description
Saves away the priority, sets up the initial transition and does any
other required initialization for this state machine

****************************************************************************/
bool InitCar(uint8_t Priority)
{
//printf("I got to InitMorseElement\r\n");
ES_Event ThisEvent;

MyPriority = Priority;

//Initialize the port lines (car PWMSs, button pins, and limit switches)

Car_Init();

//sample the port line and use it to initialize the LastInput variables
LastInput_CarPlace = HWREG(GPIO_PORTA_BASE + (GPIO_O_DATA + ALL_BITS)) & BIT7HI;
LastInput_LimitHome = HWREG(GPIO_PORTD_BASE + (GPIO_O_DATA + ALL_BITS)) & BIT2HI;
LastInput_LimitEnd = HWREG(GPIO_PORTD_BASE + (GPIO_O_DATA + ALL_BITS)) & BIT3HI;

// post the initial transition event


ThisEvent.EventType = ES_INIT;
CurrentState = InitializingCar;

if (ES_PostToService(MyPriority, ThisEvent) == true)


{
return true;
}
else
{
return false;
}
}

/****************************************************************************
Function
PostCar

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 this state machine's queue

****************************************************************************/
bool PostCar(ES_Event ThisEvent)
{
return ES_PostToService(MyPriority, ThisEvent);
}

/****************************************************************************
Function
RunCar

Parameters
ES_Event : the event to process

Returns
ES_Event, ES_NO_EVENT if no error ES_ERROR otherwise

Description
add your description here

Notes
uses nested switch/case to implement the machine.

****************************************************************************/
ES_Event RunCar(ES_Event ThisEvent)
{
ES_Event ReturnEvent;
ReturnEvent.EventType = ES_NO_EVENT; // assume no errors
static CarState_t NextState;
NextState = CurrentState;

switch (CurrentState)
{
case InitializingCar:
{
if (ThisEvent.EventType == ES_INIT)
{
NextState = WelcomeCar;
}
}
break;

case WelcomeCar:
{
if (ThisEvent.EventType == WELCOME_AUDIO)
{
NextState = WaitingForPlacement;
}

//safety precaution
if (ThisEvent.EventType == LIMIT_END)
{
Car_Stop();
}

if (ThisEvent.EventType == LIMIT_HOME)
{
Car_Stop();
}
}
break;

case WaitingForPlacement:
{
if (ThisEvent.EventType == CAR_PLACED)
{
NextState = MusicSequence;
ES_PostAll(ThisEvent);
}

if (ThisEvent.EventType == EARLY_RESET)
{
NextState = WelcomeCar;
}

//safety precaution
if (ThisEvent.EventType == LIMIT_END)
{
Car_Stop();
}

if (ThisEvent.EventType == LIMIT_HOME)
{
Car_Stop();
}
}
break;

case MusicSequence:
{
if (ThisEvent.EventType == CORRECT_NOTE)
{
//start car timer
ES_Timer_InitTimer(CarTimer, CAR_FORWARD_TIME);
//write motor drive forward
Car_Forward();
NextState = MusicSequence;
}

if (ThisEvent.EventType == LIMIT_END)
{
//write motor to stop
Car_Stop();
//write motor to reverse
Car_Reverse();

NextState = CarResetting;
}

if ((ThisEvent.EventType == ES_TIMEOUT) && (ThisEvent.EventParam ==


CarTimer))
{
//write motor to stop
Car_Stop();
NextState = MusicSequence;
}

if ((ThisEvent.EventType == TIMEOUT_POT) || (ThisEvent.EventType == VICTORY))


{
//write motor to drive forward
Car_Forward();
NextState = MovingToEnd;
}
if ((ThisEvent.EventType == HEADPHONES_RESET) || (ThisEvent.EventType ==
EARLY_RESET))
{
ResetEarly = 1;
Car_Forward();
NextState = MovingToEnd;
}
}
break;

case MovingToEnd:
{
if (ThisEvent.EventType == LIMIT_END)
{
//write motor stop
Car_Stop();
//write motor drive reverse
Car_Reverse();
NextState = CarResetting;
}

if ((ThisEvent.EventType == HEADPHONES_RESET) || (ThisEvent.EventType ==


EARLY_RESET))
{
ResetEarly = 1;
}
}
break;

case CarResetting:
{
if (ThisEvent.EventType == LIMIT_HOME)
{
//write motor stop
Car_Stop();
NextState = WaitingForHeadphones;
}

if ((ThisEvent.EventType == HEADPHONES_RESET) || (ThisEvent.EventType ==


EARLY_RESET))
{
ResetEarly = 1;
}
}
break;

case WaitingForHeadphones:
{
if ((ThisEvent.EventType == HEADPHONES_RESET) || (ResetEarly == 1))
{
ResetEarly = 0;
NextState = WelcomeCar;
}
}
break;
}
CurrentState = NextState;
return ReturnEvent;
}

/***************************************************************************
private functions
***************************************************************************/
/****************************************************************************
Function
CheckCarPlace

Parameters
None

Returns
True if an event was posted

Description
Event checker for car placement on the mount

****************************************************************************/
bool CheckCarPlace(void)
{
bool ReturnVal = false;
static uint8_t CurrentInput_CarPlace;
ES_Event ThisEvent;

CurrentInput_CarPlace = HWREG(GPIO_PORTA_BASE + (GPIO_O_DATA + ALL_BITS)) &


BIT7HI;

if ((CurrentInput_CarPlace != LastInput_CarPlace) && (CurrentInput_CarPlace |


BIT7LO))
{
ThisEvent.EventType = CAR_PLACED;
PostCar(ThisEvent);

ReturnVal = true;
}

LastInput_CarPlace = CurrentInput_CarPlace;
return ReturnVal;
}

/****************************************************************************
Function
CheckLimitEnd

Parameters
None

Returns
True if an event was posted

Description
Event checker for car hitting the limit switch at the end position

****************************************************************************/
bool CheckLimitEnd(void)
{
bool ReturnVal = false;
uint8_t CurrentInput_LimitEnd;
ES_Event ThisEvent;

CurrentInput_LimitEnd = HWREG(GPIO_PORTD_BASE + (GPIO_O_DATA + ALL_BITS)) &


BIT3HI;

if ((CurrentInput_LimitEnd != LastInput_LimitEnd) && (CurrentInput_LimitEnd))


{
ThisEvent.EventType = LIMIT_END;
PostCar(ThisEvent);
ReturnVal = true;
}

LastInput_LimitEnd = CurrentInput_LimitEnd;
return ReturnVal;
}

/****************************************************************************
Function
CheckLimitHome

Parameters
None

Returns
True if an event was posted

Description
Event checker for car hitting the limit switch at the starting position

****************************************************************************/
bool CheckLimitHome(void)
{
bool ReturnVal = false;
uint8_t CurrentInput_LimitHome;
ES_Event ThisEvent;

CurrentInput_LimitHome = HWREG(GPIO_PORTD_BASE + (GPIO_O_DATA + ALL_BITS)) &


BIT2HI;

if ((CurrentInput_LimitHome != LastInput_LimitHome) && (CurrentInput_LimitHome))


{
ThisEvent.EventType = LIMIT_HOME;
PostCar(ThisEvent);

ReturnVal = true;
}

LastInput_LimitHome = CurrentInput_LimitHome;
return ReturnVal;
}

/****************************************************************************
Function
Car_Init

Parameters
None

Returns
none

Description
returns the current state of the Template state machine

****************************************************************************/
void Car_Init(void)
{
if ((HWREG(SYSCTL_PRGPIO) & BIT0HI) != BIT0HI) // if haven't enabled the port
yet
{
// Set up port A by enabling the peripheral clock
HWREG(SYSCTL_RCGCGPIO) |= BIT0HI;
// Waiting for the peripheral to be ready
while ((HWREG(SYSCTL_PRGPIO) & BIT0HI) != BIT0HI)
{
;
}
}

if ((HWREG(SYSCTL_PRGPIO) & BIT1HI) != BIT1HI) // if haven't enabled the port


yet
{
// Set up port B by enabling the peripheral clock
HWREG(SYSCTL_RCGCGPIO) |= BIT1HI;

// Waiting for the peripheral to be ready


while ((HWREG(SYSCTL_PRGPIO) & BIT1HI) != BIT1HI)
{
;
}
}

if ((HWREG(SYSCTL_PRGPIO) & BIT3HI) != BIT3HI) // if haven't enabled the port


yet
{
// Set up port D by enabling the peripheral clock
HWREG(SYSCTL_RCGCGPIO) |= BIT3HI;

// Waiting for the peripheral to be ready


while ((HWREG(SYSCTL_PRGPIO) & BIT3HI) != BIT3HI)
{
;
}
}
// Setting PA7 to digital input
HWREG(GPIO_PORTA_BASE + GPIO_O_DEN) |= (BIT7HI);
HWREG(GPIO_PORTA_BASE + GPIO_O_DIR) &= (BIT7LO);

// Setting PD2 to digital input


HWREG(GPIO_PORTD_BASE + GPIO_O_DEN) |= (BIT2HI);
HWREG(GPIO_PORTD_BASE + GPIO_O_DIR) &= (BIT2LO);

// Setting PD3 to digital input


HWREG(GPIO_PORTD_BASE + GPIO_O_DEN) |= (BIT3HI);
HWREG(GPIO_PORTD_BASE + GPIO_O_DIR) &= (BIT3LO);

return;
}

/****************************************************************************
Function
Car_Forward

Parameters
None

Returns
none

Description
Drives car forward
Notes

****************************************************************************/
void Car_Forward(void)
{
uint8_t dutyCycle_PWM0 = PWM_DUTY_CYCLE;
uint8_t channel_PWM0 = 0;
uint8_t dutyCycle_PWM1 = 0;
uint8_t channel_PWM1 = 1;
uint16_t reqFreq = PWM_FREQ;
uint8_t group = 0;

PWM_TIVA_SetDuty( dutyCycle_PWM0, channel_PWM0);


PWM_TIVA_SetDuty( dutyCycle_PWM1, channel_PWM1);

PWM_TIVA_SetFreq(reqFreq, group);
}

/****************************************************************************
Function
Car_Reverse

Parameters
None

Returns
none

Description
Reverses car
Notes

****************************************************************************/
void Car_Reverse(void)
{
uint8_t dutyCycle_PWM1 = PWM_DUTY_CYCLE_REVERSE;
uint8_t channel_PWM1 = 1;
uint8_t dutyCycle_PWM0 = 0;
uint8_t channel_PWM0 = 0;
uint16_t reqFreq = PWM_FREQ;
uint8_t group = 0;

PWM_TIVA_SetDuty( dutyCycle_PWM0, channel_PWM0);


PWM_TIVA_SetDuty( dutyCycle_PWM1, channel_PWM1);

PWM_TIVA_SetFreq(reqFreq, group);
}

/****************************************************************************
Function
Car_Stop

Parameters
None

Returns
none

Description
Stops car
Notes

****************************************************************************/
void Car_Stop(void)
{
uint8_t dutyCycle_PWM1 = 0;
uint8_t channel_PWM1 = 0;
uint8_t dutyCycle_PWM0 = 0;
uint8_t channel_PWM0 = 1;
uint16_t reqFreq = 400;
uint8_t group = 0;

PWM_TIVA_SetDuty( dutyCycle_PWM0, channel_PWM0);


PWM_TIVA_SetDuty( dutyCycle_PWM1, channel_PWM1);

PWM_TIVA_SetFreq(reqFreq, group);
}

Potrebbero piacerti anche