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

 Module

   MasterService.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 "MasterService.h"


#include "ES_Configure.h"

#include "ES_Framework.h"

#include "dbprintf.h"

#include "CrewService.h"

#include "Servo.h"

#include "LEDService.h"

#include "string.h"

#include "PIC32_SPI_HAL.h"

#include "ButtonChecker.h"


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

#define ONE_SEC 1000

#define IDLE_SEC (ONE_SEC * 20)

#define GAMETIME_SEC (ONE_SEC * 42)

#define PROGRESS_SEC (ONE_SEC * 5)

#define RESULT_SEC (ONE_SEC * 10)

#define MESSAGE_SEC (ONE_SEC / 5)

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


MasterServiceState_t CurrentMasterState = Master_Idle;

MasterServiceState_t NextMasterState = Master_Idle;


static int progress_index = 0;

static char message[14];

static const char welcome_message[] = "2x COINs Plz ";

static const char welcome_message2[] = "1x MORE Plz! ";

static const char win_message[] = "YEAH YOU WIN ";

static const char lose_message[] = "OOPS YOU DIE ";

static const char user_left_message[] = "User Left  ";

static int string_length;

static int string_index;


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

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

 Function

     InitMasterService


 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 InitMasterService(uint8_t Priority)

{

  ES_Event_t ThisEvent;


  MyPriority = Priority;


  DB_printf("Compiled at %s on %s\r\n\n\n", __TIME__, __DATE__);


  DB_printf("\nCrew Commander ON\r\n");

  DB_printf("\nReady to Play\r\n");

  DB_printf("\nPlease Insert Two Chips\r\n");

  InitButtonChecker();

 

  InitProgressLED();


  strcpy(message, welcome_message);

  string_length = sizeof(message);

  string_index = 0;

  for (uint8_t row = 0; row < 8; row++)

  {

    DM_PutDataIntoBufferRow(0x00010000, row);

  }

  ShowMessage(ThisEvent, message);




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

   in here you write your initialization code

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

  // post the initial transition event

  // ThisEvent.EventType = ES_INIT;

  ThisEvent.EventType = ES_INIT;

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

  {

    return true;

  }

  else

  {

    return false;

  }

}


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

 Function

     PostMasterService


 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 PostMasterService(ES_Event_t ThisEvent)

{

  return ES_PostToService(MyPriority, ThisEvent);

}


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

 Function

    RunMasterService


 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 RunMasterService(ES_Event_t ThisEvent)

{

  ES_Event_t ReturnEvent;

  ReturnEvent.EventType = ES_NO_EVENT; // assume no errors

  ES_Event_t GameProgressEvent;


  switch (CurrentMasterState)

  {

  case Master_Idle:

  {

    if (ThisEvent.EventType == COIN_INSERT)

    {

      NextMasterState = One_Coin_In;

      InitProgressLED();

      ES_Timer_InitTimer(MASTERSERVICE_TIMER, IDLE_SEC);

      strcpy(message, welcome_message2);

      string_length = sizeof(message);

      string_index = 0;

      for (uint8_t row = 0; row < 8; row++)

      {

        DM_PutDataIntoBufferRow(0x00010000, row);

      }

    }

    ShowMessage(ThisEvent, message);

  }

  break;


  case One_Coin_In:

  {

    if (ThisEvent.EventType == COIN_INSERT)

    {

      NextMasterState = Game_Running;

      GameProgressEvent.EventType = GAME_START;

      progress_index = 0;

      InitProgressLED();

      ES_PostAll(GameProgressEvent);

      ES_Timer_InitTimer(MASTERSERVICE_TIMER, IDLE_SEC);

      ES_Timer_InitTimer(GAME_TIMER, GAMETIME_SEC);

      ES_Timer_InitTimer(PROGRESS_TIMER, PROGRESS_SEC);

      for (uint8_t row = 0; row < 8; row++)

      {

        DM_PutDataIntoBufferRow(0x00010000, row);

      }

      DB_printf("\rGAME START\n");

    }

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

    {

      NextMasterState = Master_Idle;

      GameProgressEvent.EventType = USER_LEFT;

      DB_printf("\rUser Left Game\n");

      strcpy(message, user_left_message);

      string_length = sizeof(message);

      string_index = 0;

      ES_PostAll(GameProgressEvent);

    }

    ShowMessage(ThisEvent, message);

  }

  break;


  case Game_Running:

  {

    if (ThisEvent.EventType == PLAYING)

    {

      NextMasterState = Game_Running;

      ES_Timer_InitTimer(MASTERSERVICE_TIMER, IDLE_SEC);

    }

    else if (ThisEvent.EventType == LOSE)

    {

      NextMasterState = Game_Complete;

      ES_Timer_InitTimer(MASTERSERVICE_TIMER, RESULT_SEC);

      ES_Timer_InitTimer(MESSAGE_TIMER, MESSAGE_SEC);

      strcpy(message, lose_message);

      string_length = sizeof(message);

      string_index = 0;

      for (uint8_t row = 0; row < 8; row++)

      {

        DM_PutDataIntoBufferRow(0x00010000, row);

      }

      DB_printf("\rYOU LOSE\n");

    }


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

    {

      NextMasterState = Game_Complete;

      GameProgressEvent.EventType = USER_LEFT;

      ES_PostAll(GameProgressEvent);

      ES_Timer_InitTimer(MASTERSERVICE_TIMER, RESULT_SEC);

      ES_Timer_InitTimer(MESSAGE_TIMER, MESSAGE_SEC);

      strcpy(message, user_left_message);

      string_length = sizeof(message);

      string_index = 0;

      for (uint8_t row = 0; row < 8; row++)

      {

        DM_PutDataIntoBufferRow(0x00010000, row);

      }

      DB_printf("\rUser Left Game\n");

    }

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

    {

      NextMasterState = Game_Complete;

      GameProgressEvent.EventType = WIN;

      ES_PostAll(GameProgressEvent);

      ES_Timer_InitTimer(MASTERSERVICE_TIMER, RESULT_SEC);

      ES_Timer_InitTimer(MESSAGE_TIMER, MESSAGE_SEC);

      strcpy(message, win_message);

      string_length = sizeof(message);

      string_index = 0;

      for (uint8_t row = 0; row < 8; row++)

      {

        DM_PutDataIntoBufferRow(0x00010000, row);

      }

      DB_printf("\rYOU WIN\n");

    }

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

    {

      NextMasterState = Game_Running;

      ES_Timer_InitTimer(PROGRESS_TIMER, PROGRESS_SEC);

     

      if (progress_index < 8)

      {

        switch(progress_index)

        {

          case 0: LATBbits.LATB4 = 1; progress_index += 1; break;  // RB4

          case 1: LATBbits.LATB5 = 1; progress_index += 1; break;  // RB5

          case 2: LATBbits.LATB6 = 1; progress_index += 1; break;  // RB6

          case 3: LATBbits.LATB2 = 1; progress_index += 1; break;  // RB7

          case 4: LATBbits.LATB8 = 1; progress_index += 1; break;  // RB8

          case 5: LATBbits.LATB9 = 1; progress_index += 1; break;  // RB9

          case 6: LATBbits.LATB10 = 1; progress_index += 1; break; // RB10

          case 7: LATBbits.LATB11 = 1; progress_index += 1; break; // RB11

        }

      }

    }

  }

  break;


  case Game_Complete:

  {

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

    {

      NextMasterState = Master_Idle;

      GameProgressEvent.EventType = GAMERESULT_OVER;

      InitProgressLED();

      PostLEDService(GameProgressEvent);

      PostServo(GameProgressEvent);

      strcpy(message, welcome_message);

      string_length = sizeof(message);

      string_index = 0;

      for (uint8_t row = 0; row < 8; row++)

      {

        DM_PutDataIntoBufferRow(0x00010000, row);

      }

      DB_printf("\rEND OF CELEBRATION\n");

    }

    ShowMessage(ThisEvent, message);

  }

  break;


  default:

  break;

  }

  CurrentMasterState = NextMasterState;


  return ReturnEvent;

}


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

 private functions

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

void ShowMessage(ES_Event_t ThisEvent, char* message)

{

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

  {

    ES_Timer_InitTimer(MESSAGE_TIMER, MESSAGE_SEC);

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

    {

      if (string_index < string_length -1)

      {

        ThisEvent.EventType = ES_NEW_KEY;

        ThisEvent.EventParam = (unsigned char)message[string_index];

        PostLEDService(ThisEvent);

        string_index++;

      }

      else

      {

        string_index = 0;

      }

    }

  }

}


void InitProgressLED(void)

{

  // Set each pin as output individually


  TRISBbits.TRISB4 = 0;   // RB4

  TRISBbits.TRISB5 = 0; // RB5

  TRISBbits.TRISB6 = 0;   // RB6

  TRISBbits.TRISB2 = 0;    // RB7

  TRISBbits.TRISB8 = 0;    // RB8

  TRISBbits.TRISB9 = 0;    // RB9

  TRISBbits.TRISB10 = 0;   // RB10

  TRISBbits.TRISB11 = 0;   // RB11

 

  // Set each pin low initially

 

  LATBbits.LATB4 = 0;     // RB4

  LATBbits.LATB5 = 0;     // RB5

  LATBbits.LATB6 = 0;     // RB6

  LATBbits.LATB2 = 0;     // RB7

  LATBbits.LATB8 = 0;     // RB8

  LATBbits.LATB9 = 0;     // RB9

  LATBbits.LATB10 = 0;    // RB10

  LATBbits.LATB11 = 0;    // RB11

}

/*------------------------------- Footnotes -------------------------------*/

/*------------------------------ End of file ------------------------------*/