Skip to content

Instantly share code, notes, and snippets.

@michaellin
Created December 1, 2015 03:57
Show Gist options
  • Save michaellin/ac3b7f48c61901e6b205 to your computer and use it in GitHub Desktop.
Save michaellin/ac3b7f48c61901e6b205 to your computer and use it in GitHub Desktop.
/****************************************************************************
Module
PipeSegment.c
Description
This service implements a state machine to control the movement of
the two pipe segments.
Author
Margaret Coad
Date
11/10/15
****************************************************************************/
/*----------------------------- Include Files -----------------------------*/
/* include header files for the framework and this service
*/
#include "ES_Configure.h"
#include "ES_Framework.h"
#include "ES_DeferRecall.h"
#include "ES_ShortTimer.h"
#include "PipeSegment.h"
#include "Audio1.h"
#include "Audio2.h"
#include "PWM12Tiva.h"
#include "BucketService.h"
#include "WrenchService.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h" // Define PART_TM4C123GH6PM in project
#include "driverlib/gpio.h"
/*----------------------------- Module Defines ----------------------------*/
#define ALL_BITS (0xff<<2)
/*---------------------------- Module Functions ---------------------------*/
/* prototypes for private functions for this service. They should be functions relevant to the behavior of this service
*/
/*---------------------------- Module Variables ---------------------------*/
// Data private to the module: MyPriority, CurrentState
static uint8_t MyPriority;
static PipeSegmentState_t CurrentState;
/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
Function
InitPipeSegment
Parameters
uint8_t : the priority 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
Margaret Coad, 11/10/15
****************************************************************************/
bool InitPipeSegment ( uint8_t Priority )
{
//Initialize the MyPriority variable with the passed in parameter
MyPriority = Priority;
//Initialize the port lines to write to PipeServo1 (PD0) and PipeServo2 //(PD1)
// Enable GPIO Port D
HWREG(SYSCTL_RCGCGPIO) |= BIT3HI;
// Wait until peripheral reports that clock is ready
while ((HWREG(SYSCTL_PRGPIO) & SYSCTL_PRGPIO_R3) !=SYSCTL_PRGPIO_R3);
// Set bits 0 and 1 on Port D to be digital I/O lines
HWREG(GPIO_PORTD_BASE+GPIO_O_DEN) |= (GPIO_PIN_0 | GPIO_PIN_1);
// Set bits 0 and 1 on Port D to be outputs
HWREG(GPIO_PORTD_BASE+GPIO_O_DIR) |= (GPIO_PIN_0 | GPIO_PIN_1);
//Initialize the port lines to write to PipeLED1 (PA4) and PipeLED2 //(PF3)
// Enable GPIO Port A
HWREG(SYSCTL_RCGCGPIO) |= BIT0HI;
// Enable GPIO Port F
HWREG(SYSCTL_RCGCGPIO) |= BIT5HI;
// Wait until peripheral reports that clock is ready
while ((HWREG(SYSCTL_PRGPIO) & SYSCTL_PRGPIO_R0) !=SYSCTL_PRGPIO_R0);
// Set bit 4 on Port A and bit 3 on Port F to be digital I/O lines
HWREG(GPIO_PORTA_BASE+GPIO_O_DEN) |= (GPIO_PIN_4);
HWREG(GPIO_PORTF_BASE+GPIO_O_DEN) |= GPIO_PIN_3;
// Set bits 4 on Port A and bit 3 on Port F to be outputs
HWREG(GPIO_PORTA_BASE+GPIO_O_DIR) |= (GPIO_PIN_4); // Pipe 1 LED
HWREG(GPIO_PORTF_BASE+GPIO_O_DIR) |= (GPIO_PIN_3); // Pipe 2 LED
//Start both pipes in the “pipes in” position
// Set frequency for the group for pins D0 and D1 to 50 Hz
PWM_TIVA_SetFreq(50, 4);
// Set pulse width on pin D0 for 0 degrees
PWM_TIVA_SetPulseWidth(700, 8);
// Set pulse width on pin D1 for 180 degrees
PWM_TIVA_SetPulseWidth(3000, 9);
//Set CurrentState to BothPipesIn
CurrentState = BothPipesIn;
//End of InitializePipeSegment (return True)
return true;
}
/****************************************************************************
Function
PostPipeSegment
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
Margaret Coad, 11/10/15
****************************************************************************/
bool PostPipeSegment( ES_Event ThisEvent )
{
return ES_PostToService( MyPriority, ThisEvent);
}
/****************************************************************************
Function
RunPipeSegment (implements 3-state state machine for pipe segments)
Parameters
ES_Event : the event to process
Returns
ES_Event, ES_NO_EVENT if no error, ES_ERROR otherwise
Description
The EventType field of ThisEvent will be one of:
ES_PIPE1_BUTTON_DBDOWN, ES_PIPE2_BUTTON_DBDOWN, ES_TIMEOUT,
ES_GAMEOVER, ES_PIPE_DOWN_LOST
Notes
Author
Margaret Coad, 11/10/15
****************************************************************************/
ES_Event RunPipeSegment( ES_Event ThisEvent )
{
ES_Event ReturnEvent;
ReturnEvent.EventType = ES_NO_EVENT; // assume no errors
//Local Variables: NextState
PipeSegmentState_t NextState;
//Set NextState to CurrentState
NextState = CurrentState;
//Based on the state of the CurrentState variable choose one of
//the following blocks of code:
switch (CurrentState){
case BothPipesIn:
// If the pipe timer goes off, we should move one of
// the pipes out
if ((ThisEvent.EventType == ES_TIMEOUT) &&
(ThisEvent.EventParam == PIPE_TIMER)) {
// Play a bad sound to show that the pipe is
// out
ES_Event ThatEvent;
ThatEvent.EventType = ES_PLAY_TUNE;
ThatEvent.EventParam = PipeOut;
PostAudio1(ThatEvent);
PostAudio2(ThatEvent);
srand(ES_Timer_GetTime());
uint8_t whichPipe = rand()%2;
// Calculate a random integer (either 0 or 1)
// to decide which pipe to move
if (whichPipe == 0){
// Move pipe 1 to the out position
// Set pulse width on pin D0 for 90
// degrees
PWM_TIVA_SetPulseWidth(2050, 8);
NextState = Pipe1Out;
// Turn on pipe 1 button LED
HWREG(GPIO_PORTA_BASE+(GPIO_O_DATA+ALL_BITS))
|= (BIT4HI);
}
else {
// Move pipe 2 to the out position
// Set pulse width on pin D1 for 90
// degrees
PWM_TIVA_SetPulseWidth(1850, 9);
NextState = Pipe2Out;
// Turn on pipe button LED
HWREG(GPIO_PORTF_BASE+(GPIO_O_DATA+ALL_BITS))
|= (BIT3HI);
}
}
// If game is over
else if (ThisEvent.EventType == ES_GAMEOVER) {
// Move into state where pipe timer will be
// ignored
NextState = InCelebration;
}
break;
case Pipe1Out:
if ((ThisEvent.EventType == ES_PIPE_DOWN_LOST) ||
(ThisEvent.EventType == ES_PIPE1_BUTTON_DBDOWN)) {
// Turn off Pipe button LEDs
HWREG(GPIO_PORTA_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT4LO);
HWREG(GPIO_PORTF_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT3LO);
// Play a good sound to show that the pipe is
back in
ES_Event ThatEvent;
ThatEvent.EventType = ES_PLAY_TUNE;
ThatEvent.EventParam = PipeIn;
PostAudio1(ThatEvent);
PostAudio2(ThatEvent);
// Post Event ES_PIPE_RECOVERED to Bucket Service,
// Wrench Service, Audio1, and Audio2
ES_Event OtherEvent;
OtherEvent.EventType = ES_PIPE_RECOVERED;
OtherEvent.EventParam = ES_Timer_GetTime();
PostBucketService(OtherEvent);
PostWrenchService(OtherEvent);
PostAudio1(OtherEvent);
PostAudio2(OtherEvent);
// Move Pipe1 to the in position
// Set pulse width on pin D0 for 0
// degrees
PWM_TIVA_SetPulseWidth(700, 8);
NextState = BothPipesIn;
// Start pipe timer for 16 seconds
ES_Timer_InitTimer(PIPE_TIMER, 16000);
}
// If game is over
else if (ThisEvent.EventType == ES_GAMEOVER) {
// Turn off pipe lights
HWREG(GPIO_PORTA_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT4LO);
HWREG(GPIO_PORTF_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT3LO);
// Set pulse width on pin D0 for 0
// degrees
PWM_TIVA_SetPulseWidth(700, 8);
NextState = InCelebration;
}
break;
case Pipe2Out:
if ((ThisEvent.EventType == ES_PIPE_DOWN_LOST) ||
(ThisEvent.EventType == ES_PIPE2_BUTTON_DBDOWN)) {
// Turn off Pipe button LEDs
HWREG(GPIO_PORTA_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT4LO);
HWREG(GPIO_PORTF_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT3LO);
// Play a good sound to show that the pipe is
// back in
ES_Event ThatEvent;
ThatEvent.EventType = ES_PLAY_TUNE;
ThatEvent.EventParam = PipeIn;
PostAudio1(ThatEvent);
PostAudio2(ThatEvent);
// Post Event ES_PIPE_RECOVERED to Bucket Service
// and Wrench Service
ES_Event OtherEvent;
OtherEvent.EventType = ES_PIPE_RECOVERED;
OtherEvent.EventParam = ES_Timer_GetTime();
PostBucketService(OtherEvent);
PostWrenchService(OtherEvent);
PostAudio1(OtherEvent);
PostAudio2(OtherEvent);
// Move Pipe2 to the in position
// Set pulse width on pin D1 for 180
// degrees
PWM_TIVA_SetPulseWidth(3000, 9);
NextState = BothPipesIn;
// Start pipe timer for 16 seconds
ES_Timer_InitTimer(PIPE_TIMER, 16000);
}
// If the game is over
else if (ThisEvent.EventType == ES_GAMEOVER) {
// Turn off button lights
HWREG(GPIO_PORTA_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT4LO);
HWREG(GPIO_PORTF_BASE+(GPIO_O_DATA+ALL_BITS))
&= (BIT3LO);
// Set pulse width on pin D1 for 180
// degrees
PWM_TIVA_SetPulseWidth(3000, 9);
NextState = InCelebration;
}
break;
case InCelebration:
if (ThisEvent.EventType == ES_START_BUTTON_DBDOWN)
{
NextState = BothPipesIn;
}
break;
}
//Set CurrentState to NextState
CurrentState = NextState;
//Return ES_NO_EVENT
return ReturnEvent;
}
/***************************************************************************
private functions
***************************************************************************/
/*------------------------------- Footnotes -------------------------------*/
/*------------------------------ End of file ------------------------------*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment