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

 Module

   TemplateFSM.c


 Revision

   1.0.1


 Description

   This is a template file for implementing 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 "LEDService.h"

#include "PIC32_SPI_HAL.h"

#include "ES_Configure.h"

#include "ES_Framework.h"

#include "TemplateFSM.h"

#include "DM_Display.h"

#include "FontStuff.h"

#include "ES_Events.h" // needed for definition of REENTRANT

#include "dbprintf.h"


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

#define ONE_SEC 1000

#define HALF_SEC (ONE_SEC /2)


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

/* prototypes for private functions for this machine.They should be functions

   relevant to the behavior of this state machine

*/


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

static LEDServiceState_t CurrentState;


// with the introduction of Gen2, we need a module level Priority var as well

static uint8_t MyPriority;


static uint32_t col[] = {0x00000001, 0x00000001 << 1, 0x00000001 << 2, 0x00000001 << 3, 0x00000001 << 4, 0x00000001 << 5, 0x00000001 << 6, 0x00000001 << 7, 0x00000001 << 8,

                         0x00000001 << 9, 0x00000001 << 10, 0x00000001 << 11, 0x00000001 << 12, 0x00000001 << 13, 0x00000001 << 14, 0x00000001 << 15, 0x00000001 << 16,

                         0x00000001 << 17, 0x00000001 << 18, 0x00000001 << 19, 0x00000001 << 20, 0x00000001 << 21, 0x00000001 << 22, 0x00000001 << 23, 0x00000001 << 24,

                         0x00000001 << 25, 0x00000001 << 26, 0x00000001 << 27, 0x00000001 << 28, 0x00000001 << 29, 0x00000001 << 30, 0x00000001 << 31};

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

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

 Function

     InitTemplateFSM


 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

 Notes


 Author

     J. Edward Carryer, 10/23/11, 18:55

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

bool InitLEDService(uint8_t Priority)

{

  ES_Event_t ThisEvent;


  SPI_Module_t module = SPI_SPI1;

  SPI_SamplePhase_t phase = SPI_SMP_MID;


  SPISetup_DisableSPI(module);

  SPISetup_BasicConfig(module);

  //    SPI1BUF;

  SPISetup_SetLeader(module, phase);

  SPISetup_SetBitTime(module, 10000);

  SPISetup_MapSSOutput(module, SPI_RPA0);

  SPISetup_MapSDOutput(module, SPI_RPA1);

  SPISetup_SetClockIdleState(module, SPI_CLK_LO); // CKP

  SPISetup_SetActiveEdge(module, SPI_FIRST_EDGE); // CKE

  SPISetup_SetXferWidth(module, SPI_16BIT);

  SPISetEnhancedBuffer(module, 1);

  SPISetup_EnableSPI(module);

  IFS0CLR = _IFS0_INT1IF_MASK; // clear any pending flag


  while (!DM_TakeInitDisplayStep())

  {

  }


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

  {

    DM_PutDataIntoBufferRow(0x00010000, row);

  }


  while (!DM_TakeDisplayUpdateStep())

  {

  }


  MyPriority = Priority;

  // put us into the Initial PseudoState

  CurrentState = InitState;

  // post the initial transition event

  ThisEvent.EventType = ES_INIT;


  // DB_printf("\r Init \n");

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

  {

    return true;

  }

  else

  {

    return false;

  }

}


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

 Function

     PostTemplateFSM


 Parameters

     EF_Event_t 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

 Notes


 Author

     J. Edward Carryer, 10/23/11, 19:25

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

bool PostLEDService(ES_Event_t ThisEvent)

{

  return ES_PostToService(MyPriority, ThisEvent);

}


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

 Function

    RunTemplateFSM


 Parameters

   ES_Event_t : the event to process


 Returns

   ES_Event_t, ES_NO_EVENT if no error ES_ERROR otherwise


 Description

   add your description here

 Notes

   uses nested switch/case to implement the machine.

 Author

   J. Edward Carryer, 01/15/12, 15:23

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

ES_Event_t RunLEDService(ES_Event_t ThisEvent)

{

  ES_Event_t ReturnEvent;

  ReturnEvent.EventType = ES_NO_EVENT; // assume no errors

  // char c = '1';

  switch (CurrentState)

  {

    case InitState: // If current state is initial Psedudo State

    {

     

      if (ThisEvent.EventType == ES_INIT) // only respond to ES_Init

      {

        CurrentState = Waiting;

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

        {

          DM_PutDataIntoBufferRow(0x00010000, row);

        }

        CurrentState = Updating;

        ThisEvent.EventType = ES_DISPLAY_UPDATE_STEP;

        PostLEDService(ThisEvent);

        // DB_printf("\r moving to waiting \n");

      }

    }

    break;


    case Waiting: // If current state is state one

    {

      switch (ThisEvent.EventType)

      {

        case ES_NEW_KEY: // If event is event one

        {                // Execute action function for state one : event one

          DM_ScrollDisplayBuffer(4, 0);

          DM_AddChar2DisplayBuffer(ThisEvent.EventParam);

          CurrentState = Updating;

          ThisEvent.EventType = ES_DISPLAY_UPDATE_STEP;

          // DB_printf("\r got a key \n");

          PostLEDService(ThisEvent);

        }

        break;


        //          case LEFT_DOWN:

        //          {

        //                            DB_printf("%d\n", ThisEvent.EventParam);

        //

        ////            DM_ScrollDisplayBuffer(1, 0);

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

        //              DM_PutDataIntoBufferRow(col[ThisEvent.EventParam], row);

        //             }

        //            CurrentState = Updating;

        //            ThisEvent.EventType = ES_DISPLAY_UPDATE_STEP;

        //            PostLEDService(ThisEvent);

        //

        //          }

        //          break;


        case NEW_CREW_POSITION:

        {

          // DM_ScrollDisplayBuffer(1, 1);

          // DB_printf("Crew Position: %d\n", ThisEvent.EventParam);

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

          {

            DM_PutDataIntoBufferRow(col[ThisEvent.EventParam], row);

          }

          CurrentState = Updating;

          ThisEvent.EventType = ES_DISPLAY_UPDATE_STEP;

          PostLEDService(ThisEvent);

        }

        break;


        case GAME_START:

        {

          CurrentState = InitPState;

          ThisEvent.EventType = ES_INIT;

          PostLEDService(ThisEvent);

        }



        default:

        break;

      } // end switch on CurrentEvent

    }

    break;


    case Updating: // If current state is state one

    {

      switch (ThisEvent.EventType)

      {

        case ES_DISPLAY_UPDATE_STEP: // If event is event one

        { // Execute action function for state one : event one

          if (!DM_TakeDisplayUpdateStep())

          {

            PostLEDService(ThisEvent);

          }

          else

          {

            CurrentState = Waiting;

            //                    DM_ClearDisplayBuffer(4);

          }

        }

        break;


        default:

        break;

      } // end switch on CurrentEvent

    }

    break;

    // repeat state pattern as required for other states

    default:

    break;;

  } // end switch on Current State

  return ReturnEvent;

}


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

 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, 10/23/11, 19:21

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

TemplateState_t QueryTemplateFSM(void)

{

  return CurrentState;

}


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

 private functions

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