/**************************************************************************** Module JSR.c Revision 2.0.1 Description This is a template file for implementing state machines. Notes History When Who What/Why -------------- --- -------- 02/16/14 bc created ****************************************************************************/ /*----------------------------- Include Files -----------------------------*/ // Basic includes for a program using the Events and Services Framework #include "ES_Configure.h" #include "ES_Framework.h" /* 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 "JSR.h" #include "MasterSM.h" #include "Commands.h" #include <mc9s12e128.h> #include <S12E128Bits.h> #include <stdio.h> #include "Pins.h" /*----------------------------- Module Defines ----------------------------*/ // define constants for the states for this machine // and any other local defines #define DDR_SLAVE_SEL DDRS #define PORT_SLAVE_SEL PTS #define PIN_SLAVE_SEL BIT7HI /*---------------------------- Module Functions ---------------------------*/ /* prototypes for private functions for this machine, things like during functions, entry & exit functions.They should be functions relevant to the behavior of this state machine */ static ES_Event DuringWaiting( ES_Event Event); static ES_Event DuringStatusCommandByte( ES_Event Event); static ES_Event DuringReadByte( ES_Event Event); static ES_Event DuringTransferByte( ES_Event Event); static ES_Event DuringScoreCommandByte( ES_Event Event); static void InitSPI(void); static unsigned char readJSR(void); static void MapCommandToEvent(unsigned char); /*---------------------------Public Query Functions -----------------------*/ unsigned char RedKnightScore(void); unsigned char DarkKnightScore(void); /*---------------------------- Module Variables ---------------------------*/ // everybody needs a state variable, you may need others as well static JSRState_t CurrentState; static unsigned char receivedByte; static bool ReadSuccessful;// = false; static bool TransferSuccessful;// = false; static unsigned char darkKnightScore; static unsigned char redKnightScore; static int knight; static bool reloadAllowed; static uint8_t MyPriority; /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function InitJSR Parameters uint8_t : the priorty of this service Returns boolean, False if error in initialization, True otherwise Description Saves away the priority, and starts the top level state machine Notes Author J. Edward Carryer, 02/06/12, 22:06 ****************************************************************************/ bool InitJSR ( uint8_t Priority ) { ES_Event ThisEvent; MyPriority = Priority; // save our priority ThisEvent.EventType = ES_ENTRY; //If toggle is high -> dark knight if((PORT_KNIGHT_TOGGLE & PIN_KNIGHT_TOGGLE) == PIN_KNIGHT_TOGGLE) { knight = DARK_KNIGHT; printf("Dark Knight \n\r"); } else{ knight = RED_KNIGHT; printf("Red Knight \n\r"); } reloadAllowed = false; //start hardware SPI initialization InitSPI(); StartJSR( ThisEvent ); return true; } /**************************************************************************** Function PostJSR Parameters ES_Event ThisEvent , the event to post to the queue Returns boolean False if the post 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 PostJSR( ES_Event ThisEvent ) { return ES_PostToService( MyPriority, ThisEvent); } /**************************************************************************** Function RunJSR Parameters ES_Event: the event to process Returns ES_Event: an event to return Description This is the SPI-JSR communications main run function ****************************************************************************/ ES_Event RunJSR( ES_Event CurrentEvent ) { unsigned char MakeTransition = false;/* are we making a state transition? */ JSRState_t NextState = CurrentState; //ES_Event EntryEventKind = { ES_ENTRY, 0 };// default to normal entry to new state ES_Event ReturnEvent = CurrentEvent; // assume we are not consuming event switch ( CurrentState ) { case ST_Waiting : // call during function for this state CurrentEvent = DuringWaiting(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout //check for ES_TIMEOUT from QUERY_TIMER and start SPI/JSR sequence if ( QUERY_TIMER == CurrentEvent.EventParam) { MakeTransition = true; NextState = ST_PausingForSS; ES_Timer_SetTimer(TRANSFER_TIMER, TRANSFER_INTERVAL); ES_Timer_StartTimer(TRANSFER_TIMER); ReturnEvent.EventType = ES_NO_EVENT; /* // Set next state to SendingByte1 NextState = SendingByte1; //Decide what the next state will be // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; */ } break; }//end switch }//end if break; case ST_PausingForSS: if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout //check for ES_TIMEOUT from QUERY_TIMER and start SPI/JSR sequence if ( TRANSFER_TIMER == CurrentEvent.EventParam) { // Set next state to SendingByte1 NextState = ST_SendingByte1; //Decide what the next state will be // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; } break; }//end switch }//end if break; case ST_SendingByte1 : // sending first command byte (status) // call during function for this state CurrentEvent = DuringStatusCommandByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // Set next state to SendingByte2 NextState = ST_SendingByte2; //Decide what the next state will be }//end if TransferSuccessful // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; }//END if EventParam break; }//end switch } break; case ST_SendingByte2 : // call during function for this state CurrentEvent = DuringTransferByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // Set next state NextState = ST_SendingByte3; //Decide what the next state will be } // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; }// end if EventParam break; }//end switch }//end if break; case ST_SendingByte3 : // call during function for this state CurrentEvent = DuringTransferByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // Set next state to SendingByte4 NextState = ST_SendingByte4; //Decide what the next state will be } // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; } //end if EventParam break; }//end switch }//end if break; case ST_SendingByte4 : // call during function for this state CurrentEvent = DuringTransferByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // Set next state to SendingByte5 NextState = ST_ReadByte4; //Decide what the next state will be } // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; }// end if EventParam break; }//end switch }//end if break; case ST_ReadByte4 : // call during function for this state CurrentEvent = DuringReadByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { MakeTransition = true; // consume event, unless read successful below ReturnEvent.EventType = ES_NO_EVENT; if(ReadSuccessful) { // reset transfer success flag ReadSuccessful = false; // Debug prints //printf("Status: %3d, \n\r", receivedByte); // Set next state to SendingByte5 NextState = ST_SendingByte5; //Decide what the next state will be // Remap the event to the received game status MapCommandToEvent(receivedByte); } }// end if EventParam break; }//end switch }//end if break; case ST_SendingByte5 : // call during function for this state CurrentEvent = DuringScoreCommandByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // Set next state to SendingByte6 NextState = ST_SendingByte6; //Decide what the next state will be } // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; }// end if EventParam break; }//end switch }//end if break; case ST_SendingByte6 : // call during function for this state CurrentEvent = DuringTransferByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // Set next state to SendingByte7 NextState = ST_SendingByte7; //Decide what the next state will be } // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; }// end EventParam break; }//end switch }//end if break; case ST_SendingByte7 : // call during function for this state CurrentEvent = DuringTransferByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // Set next state to SendingByte8 NextState = ST_SendingByte8; //Decide what the next state will be } // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; }// end if EventParam break; }//end switch }//end if break; case ST_SendingByte8 : // call during function for this state CurrentEvent = DuringTransferByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(TransferSuccessful) { // reset transfer success flag TransferSuccessful = false; // update red knight score redKnightScore = receivedByte; // Set next state to TransferComplete NextState = ST_ReadByte8; //Decide what the next state will be // Debug prints // printf("Red Score: %*d \n\r", 3, redKnightScore); } // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // consume this event ReturnEvent.EventType = ES_NO_EVENT; }//end if EventParam break; }//end switch }//end if break; case ST_ReadByte8 : // call during function for this state CurrentEvent = DuringReadByte(CurrentEvent); //process any events if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT : //If event is a timeout if ( TRANSFER_TIMER == CurrentEvent.EventParam) //check if it is the right source of ES_TIMEOUT { if(ReadSuccessful) { // reset transfer success flag ReadSuccessful = false; // update darkKnight score, the byte8 darkKnightScore = receivedByte; // Raise SS Line DDR_SLAVE_SEL |= PIN_SLAVE_SEL; //transition to waiting MakeTransition = true; //Transition to Waiting state NextState = ST_Waiting; // Debug prints // printf("Dark Score: %*d \n\r", 3, darkKnightScore); } else { // make an external self transition if read was not successful MakeTransition = true; } // consume this event ReturnEvent.EventType = ES_NO_EVENT; }//end if EventParam break; }//end switch on EventType }//end if break; }// end switch on current state // If we are making a state transition if (true == MakeTransition ) { // Execute exit function for current state CurrentEvent.EventType = ES_EXIT; RunJSR(CurrentEvent); CurrentState = NextState; //Modify state variable // Execute entry function for new state // set event type to ES_ENTRY CurrentEvent.EventType = ES_ENTRY; RunJSR(CurrentEvent); } return(ReturnEvent); } /**************************************************************************** Function StartJSR Parameters None Returns None Description Does any required initialization for this state machine Notes ****************************************************************************/ void StartJSR ( ES_Event CurrentEvent ) { // local variable to get debugger to display the value of CurrentEvent volatile ES_Event LocalEvent = CurrentEvent; // to implement entry to a history state or directly to a substate // you can modify the initialization of the CurrentState variable // otherwise just start in the entry state every time the state machine // is started if ( ES_ENTRY_HISTORY != CurrentEvent.EventType ) { CurrentState = ST_Waiting; } ReadSuccessful = false; TransferSuccessful = false; // call the entry function (if any) for the ENTRY_STATE RunJSR(CurrentEvent); } /**************************************************************************** Function QueryJSR 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, 2/11/05, 10:38AM ****************************************************************************/ JSRState_t QueryJSR ( void ) { return(CurrentState); } /**************************************************************************** Function RedKnightScore Parameters None Returns unsigned char the current score for the red knight Description the current score for the red knight Notes Author Chih-Wei Tang, 2/17/2014 ****************************************************************************/ unsigned char RedKnightScore(void){ return redKnightScore; } /**************************************************************************** Function DarkKnightScore Parameters None Returns unsigned char the current score for the dark knight Description the current score for the dark knight Notes Author Chih-Wei Tang, 2/17/2014 ****************************************************************************/ unsigned char DarkKnightScore(void){ return darkKnightScore; } bool QueryReload(void){ return reloadAllowed; } /*************************************************************************** private functions ***************************************************************************/ static void MapCommandToEvent(unsigned char receivedStatus){ //unsigned char command; ES_Event StatusEvent; //Check Bits 0-2 unsigned char command = (receivedStatus & COMM_MASK_LSB); StatusEvent.EventType = ES_NO_EVENT; //printf("Received: %d, Command: %d \n\r", receivedStatus, command); switch(command) { case COMM_MATCH_UNDERWAY : StatusEvent.EventType = EV_PAS_DARMES; break; case COMM_WAITING : StatusEvent.EventType = ES_NO_EVENT; break; case COMM_RECESS : StatusEvent.EventType = EV_RECESS; break; case COMM_SUDDEN_DEATH : StatusEvent.EventType = EV_SUDDEN_DEATH; break; case COMM_END_MATCH : StatusEvent.EventType = EV_END_MATCH; break; } PostMasterSM(StatusEvent); //TODO: Check Unhorsed and Reload Bits if(knight == DARK_KNIGHT){ if((receivedStatus & COMM_RELOAD_DARK_OK) == COMM_RELOAD_DARK_OK){ reloadAllowed = true; } } else{ if((receivedStatus & COMM_RELOAD_RED_OK) == COMM_RELOAD_RED_OK){ reloadAllowed = true; } } } static void sendCommand(char command) { // Read SPISR with SPTEF Hi if((SPISR&_S12_SPTEF) == _S12_SPTEF) { //Write to SPIDR SPIDR = command; TransferSuccessful = true; } else{ printf("Error: send register flag not set\r\n"); TransferSuccessful = false; } } static unsigned char readJSR(void){ static unsigned char data = 0; //Read SPISR with SPIF Hi, if((SPISR&_S12_SPIF) == _S12_SPIF) { //Read SPIDR data = SPIDR; ReadSuccessful = true; //printf("\r\n%u\r\n", data); //return the 8 bit data return data; } else if((SPISR&_S12_MODF) == _S12_MODF) { printf("MODF SET \n\r"); ReadSuccessful = false; return 0; } else{ printf("Error: receive register flag not set\r\n"); ReadSuccessful = false; return 0; } } /*************************************************************************** During Functions ***************************************************************************/ static ES_Event DuringWaiting( ES_Event Event) { //ES_Event ReturnEvent = Event; // process ES_ENTRY and ES_EXIT events if ( (Event.EventType == ES_ENTRY) ) { //Start Query Timer ES_Timer_SetTimer(QUERY_TIMER, QUERY_INTERVAL); ES_Timer_StartTimer(QUERY_TIMER); //printf("Start Waiting \n\r"); } else if ( (Event.EventType == ES_EXIT) ) { PORT_SLAVE_SEL &= ~PIN_SLAVE_SEL; //start transfer timer } // do the 'during' function for this state { // no during function in this state } // don't remap the event return(Event); } static ES_Event DuringStatusCommandByte( ES_Event Event) { // process ES_ENTRY and ES_EXIT events if ( (Event.EventType == ES_ENTRY) ) { // send status command sendCommand(QUERY_STATUS); // start transfer timer ES_Timer_SetTimer(TRANSFER_TIMER, TRANSFER_INTERVAL); ES_Timer_StartTimer(TRANSFER_TIMER); } else // do the 'during' function for this state { // no during function in this state } // don't remap the event return(Event); } static ES_Event DuringScoreCommandByte( ES_Event Event) { //ES_Event ReturnEvent = Event; //no event consumption //check event type for ES_ENTRY, ES_EXIT if (ES_ENTRY == Event.EventType) { //send score query command sendCommand(QUERY_SCORE); //start transfer timer ES_Timer_SetTimer(TRANSFER_TIMER, TRANSFER_INTERVAL); ES_Timer_StartTimer(TRANSFER_TIMER); } else if (ES_EXIT == Event.EventType) { //do the local exit function } else { // do the during function for this state // No during function for this machine } return (Event); //Don't remap this event } static ES_Event DuringTransferByte(ES_Event Event) { if (ES_ENTRY == Event.EventType) { // Byte hasn't been read yet -> Read Byte if(~ReadSuccessful) { //read previous byte receivedByte = readJSR(); } if(ReadSuccessful) { //send command of 0x00 sendCommand(COMM_WAITING); //byte 7 is the score for RedKnight if ( ST_SendingByte8 == CurrentState){ redKnightScore = receivedByte; } if(TransferSuccessful) { // reset read success flag ReadSuccessful = false; } } //start Transfer timer ES_Timer_SetTimer(TRANSFER_TIMER, TRANSFER_INTERVAL); ES_Timer_StartTimer(TRANSFER_TIMER); } else if (ES_EXIT == Event.EventType) { //do the local exit function } else { // do the during function for this state // No durring function for this machine } return (Event); //Don't remap this event } static ES_Event DuringReadByte( ES_Event Event) { if (ES_ENTRY == Event.EventType) { // read last byte of this query receivedByte = readJSR(); //read successful flag check is within the state //start Transfer timer ES_Timer_SetTimer(TRANSFER_TIMER, TRANSFER_INTERVAL); ES_Timer_StartTimer(TRANSFER_TIMER); } else if (ES_EXIT == Event.EventType) { // no exit function } else { // do the during function for this state // No during function for this machine } return (Event); //Don't remap this event } /* Hardware Initialization Functions */ static void InitSPI(void){ puts("Init SPI \n\r"); //Set to Master (SPICR1) SPICR1 |= _S12_MSTR; //SPI Enable (SPICR1) SPICR1 |= _S12_SPE; //MSB First (SPICR1) SPICR1 &= ~_S12_LSFBE; // currently not enabling interrupts //Interrupt Enable (SPICR1) //SPICR1 |= _S12_SPIE; //Transmit Enable (SPICR1) //SPICR1 |= _S12_SPTIE; //Clock Polarity (SPICR1) SPICR1 |= _S12_CPOL; //Clock Phase (SPICR1) SPICR1 |= _S12_CPHA; //Mode 3 - SSOE LO, MODFEN HI //Slave Select Output Enable(SPICR1) //SPICR1 |= _S12_SSOE; SPICR1 &= ~_S12_SSOE; // Mode 0 // Mode Fault Enable (SPICR2) //SPICR2 |= _S12_MODFEN; SPICR2 &= ~_S12_MODFEN; // SPI Bit Rate - Divisor of 32 SPIBR = _S12_SPR0 | _S12_SPR1 | _S12_SPPR0; DDR_SLAVE_SEL |= PIN_SLAVE_SEL; PORT_SLAVE_SEL |= PIN_SLAVE_SEL; //EnableInterrupts; }