/****************************************************************************
Module
CrewService.c
Revision
1.0.1
Description
This is a template file for implementing a simple service under the
Gen2 Events and Services Framework.
Notes
History
When Who What/Why
-------------- --- --------
01/16/12 09:58 jec began conversion from TemplateFSM.c
****************************************************************************/
/*----------------------------- 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
*/
//This Module
#include "CrewService.h"
#include "ES_Configure.h"
#include "ES_Framework.h"
#include "dbprintf.h"
#include "DebouncingService.h"
#include "MasterService.h"
#include "LEDService.h"
#include "Servo.h"
#include "PIC32_AD_Lib.h"
/*----------------------------- Module Defines ----------------------------*/
#define ONE_SEC 1000
#define CREW_UPDATE_FREQUENCY 10
#define CREW_UPDATE_SEC (ONE_SEC /CREW_UPDATE_FREQUENCY)
#define MAX_POSITION 6400
#define MIN_POSITION 0
#define NEUTRAL_POSITION ((MAX_POSITION + MIN_POSITION)/2)
#define MAX_SPEED 5000
#define MAX_MIC_VOLUME 1023
#define MIN_MIC_VOLUME 0
#define ROWS_LEDMATRIX 32
#define AD_CHANNEL (1<<5)
#define NUM_AD_CHANNELS 1
/*---------------------------- Module Functions ---------------------------*/
/* prototypes for private functions for this service.They should be functions
relevant to the behavior of this service
*/
/*---------------------------- Module Variables ---------------------------*/
// with the introduction of Gen2, we need a module level Priority variable
static uint8_t MyPriority;
static int32_t CurrentAD_Value[NUM_AD_CHANNELS];
static int16_t MicVolume = 0;
static int16_t NormalizedCrewPosition = 16;
Crew_Movement_t CrewMovement;
CrewServiceState_t CurrentState = InitCrew;
CrewServiceState_t NextState = InitCrew;
/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
Function
InitCrewService
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
J. Edward Carryer, 01/16/12, 10:00
****************************************************************************/
bool InitCrewService(uint8_t Priority)
{
ES_Event_t ThisEvent;
MyPriority = Priority;
ADC_ConfigAutoScan(AD_CHANNEL);
ADC_MultiRead(CurrentAD_Value);
CrewMovement.Direction = Stop;
CrewMovement.Position = NEUTRAL_POSITION;
CrewMovement.Speed = MAX_SPEED /10;
/********************************************
in here you write your initialization code
*******************************************/
// post the initial transition event
ThisEvent.EventType = ES_INIT;
if (ES_PostToService(MyPriority, ThisEvent) == true)
{
return true;
}
else
{
return false;
}
}
/****************************************************************************
Function
PostCrewService
Parameters
EF_Event_t 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
J. Edward Carryer, 10/23/11, 19:25
****************************************************************************/
bool PostCrewService(ES_Event_t ThisEvent)
{
return ES_PostToService(MyPriority, ThisEvent);
}
/****************************************************************************
Function
RunCrewService
Parameters
ES_Event_t : the event to process
Returns
ES_Event, ES_NO_EVENT if no error ES_ERROR otherwise
Description
add your description here
Notes
Author
J. Edward Carryer, 01/15/12, 15:23
****************************************************************************/
ES_Event_t RunCrewService(ES_Event_t ThisEvent)
{
ES_Event_t ReturnEvent;
ReturnEvent.EventType = ES_NO_EVENT; // assume no errors
ES_Event_t UserInteract;
switch (CurrentState)
{
case InitCrew:
{
if (ThisEvent.EventType == GAME_START) // only respond to GAME_START
{
NextState = Idle;
CrewMovement.Direction = Stop;
CrewMovement.Position = NEUTRAL_POSITION;
CrewMovement.Speed = MAX_SPEED /10;
}
}
break;
case Idle:
{
if (ThisEvent.EventType == LEFT_DOWN)
{
NextState = Left_Down;
CrewMovement.Direction = Left;
ES_Timer_InitTimer(CREWSERVICE_TIMER, CREW_UPDATE_SEC);
}
else if (ThisEvent.EventType == RIGHT_DOWN)
{
NextState = Right_Down;
CrewMovement.Direction = Right;
ES_Timer_InitTimer(CREWSERVICE_TIMER, CREW_UPDATE_SEC);
}
else if (ThisEvent.EventType == USER_LEFT || ThisEvent.EventType == WIN || ThisEvent.EventType == LOSE)
{
NextState = InitCrew;
}
}
break;
case Left_Down:
{
if (ThisEvent.EventType == LEFT_UP)
{
NextState = Idle;
CrewMovement.Direction = Stop;
}
else if (ThisEvent.EventType == RIGHT_DOWN)
{
NextState = Both_Down;
CrewMovement.Direction = Stop;
}
else if (ThisEvent.EventType == ES_TIMEOUT && ThisEvent.EventParam == CREWSERVICE_TIMER)
{
NextState = Left_Down;
ES_Timer_InitTimer(CREWSERVICE_TIMER, CREW_UPDATE_SEC);
UpdateCrewPosition();
}
if (ThisEvent.EventType == USER_LEFT || ThisEvent.EventType == WIN || ThisEvent.EventType == LOSE)
{
NextState = InitCrew;
}
UserInteract.EventType = PLAYING;
PostMasterService(UserInteract);
}
break;
case Right_Down:
{
if (ThisEvent.EventType == RIGHT_UP)
{
NextState = Idle;
CrewMovement.Direction = Stop;
}
else if (ThisEvent.EventType == LEFT_DOWN)
{
NextState = Both_Down;
CrewMovement.Direction = Stop;
}
else if (ThisEvent.EventType == ES_TIMEOUT && ThisEvent.EventParam == CREWSERVICE_TIMER)
{
NextState = Right_Down;
ES_Timer_InitTimer(CREWSERVICE_TIMER, CREW_UPDATE_SEC);
UpdateCrewPosition();
}
if (ThisEvent.EventType == USER_LEFT || ThisEvent.EventType == WIN || ThisEvent.EventType == LOSE)
{
NextState = InitCrew;
}
UserInteract.EventType = PLAYING;
PostMasterService(UserInteract);
}
break;
case Both_Down:
{
if (ThisEvent.EventType == LEFT_UP)
{
NextState = Right_Down;
CrewMovement.Direction = Right;
ES_Timer_InitTimer(CREWSERVICE_TIMER, CREW_UPDATE_SEC);
}
else if (ThisEvent.EventType == RIGHT_UP)
{
NextState = Left_Down;
CrewMovement.Direction = Left;
ES_Timer_InitTimer(CREWSERVICE_TIMER, CREW_UPDATE_SEC);
}
if (ThisEvent.EventType == USER_LEFT || ThisEvent.EventType == WIN || ThisEvent.EventType == LOSE)
{
NextState = InitCrew;
}
UserInteract.EventType = PLAYING;
PostMasterService(UserInteract);
}
break;
default:
break;
}
CurrentState = NextState;
return ReturnEvent;
}
/***************************************************************************
private functions
***************************************************************************/
void UpdateCrewSpeed(void)
{
ADC_MultiRead(CurrentAD_Value);
MicVolume = abs((uint16_t)CurrentAD_Value[0]);
CrewMovement.Speed = MAX_SPEED * (MicVolume - MIN_MIC_VOLUME) / (MAX_MIC_VOLUME - MIN_MIC_VOLUME);
return;
}
void UpdateCrewPosition(void)
{
ES_Event_t CrewPositionEvent;
CrewPositionEvent.EventParam = 16;
UpdateCrewSpeed();
if (CrewMovement.Direction == Left)
{
if (CrewMovement.Position > MIN_POSITION)
{
CrewMovement.Position -= CrewMovement.Speed /CREW_UPDATE_FREQUENCY;
}
else
{
CrewMovement.Position = MIN_POSITION;
}
}
if (CrewMovement.Direction == Right)
{
if (CrewMovement.Position < MAX_POSITION)
{
CrewMovement.Position += CrewMovement.Speed /CREW_UPDATE_FREQUENCY;
}
else
{
CrewMovement.Position = MAX_POSITION;
}
}
NormalizedCrewPosition = (ROWS_LEDMATRIX - 1) * CrewMovement.Position / (MAX_POSITION - MIN_POSITION);
CrewPositionEvent.EventType = NEW_CREW_POSITION;
CrewPositionEvent.EventParam = NormalizedCrewPosition;
PostLEDService(CrewPositionEvent);
PostServo(CrewPositionEvent);
return;
}
/*------------------------------- Footnotes -------------------------------*/
/*------------------------------ End of file *------------------------------*/