#include <htc.h>
#include "pic16f690.h"
#include <stdio.h>
#include "bitdefs.h"
#include "ACVXbeePicUART.h"

/*----------------- Module Definitions ------------------*/
typedef enum {
    Main_Idle = 0,
    //Team Finding States:
    Main_Listening = 1,
    Main_Confirming = 2,
    Main_Seeking = 3,
    Main_Timeout = 5,
    //Capturing Atoll States:
    Main_Capturing = 4,
    Main_Pending = 6,
    Main_Announcing = 7
} MainState_t;

/*------------------ Module Functions -------------------*/
static void InitMain(void);
static void InitTimer2(void);
static void InitMotors(void);

static void UpdateMainStateMachine(void);
static void UpdateTimer2(void);
static void UpdateMotors(void);

static unsigned char IdentifyColor(unsigned char S1, unsigned char S2, unsigned char S3);
static unsigned char IdentifyAtoll(unsigned char S1, unsigned char S2, unsigned char S3);

/*------------------ Module Variables -------------------*/
//Message Flags
static unsigned char NewXbeeMessageFlag = 0;
static unsigned char NewSPIColorFlag = 0;
static unsigned char NewSPIAtollFlag = 0;

//Gameplay initialization
static MainState_t MainState = Main_Idle;
static unsigned char MyTeam = Team_None;
static unsigned char MyFlag = Servo_None;

//Transmission bytes
static unsigned char Address_TeammateHigh;
static unsigned char Address_TeammateLow;

static unsigned char AtollNumber;
static unsigned char CardColor;

static unsigned char FrameID_Confirming = 0x01;
static unsigned char FrameID_Seeking = 0x02;
static unsigned char FrameID_Capturing = 0x03;
static unsigned char FrameID_Announcing = 0x04;

static unsigned char Atoll_S1;
static unsigned char Atoll_S2;
static unsigned char Atoll_S3;
static unsigned char Atoll_SK1;
static unsigned char Atoll_SK2;
static unsigned char Atoll_SK3;


//Main State Machine Timers and Timer Flags
static unsigned char Timer_Listening;
static unsigned char Timer_Confirming;
static unsigned char Timer_Flags;
static unsigned char Timer_Capturing;
static unsigned char Timer_Pending;
static unsigned char Timer_Announcing;

static unsigned char TimerFlag_Listening = 0;
static unsigned char TimerFlag_Confirming = 0;
static unsigned char TimerFlag_Flags = 0;
static unsigned char TimerFlag_Capturing = 0;
static unsigned char TimerFlag_Pending = 0;
static unsigned char TimerFlag_Announcing = 0;

//Main state machine counter variables and flags
static unsigned char Counter_Confirming = 0;
static unsigned char Counter_Seeking = 0;
static unsigned char Counter_Flags = 0;
static unsigned char Counter_Capturing = 0;
static unsigned char Counter_Pending = 0;
static unsigned char Counter_Announcing = 0;

static unsigned char Flag_Capturing = 0;
static unsigned char Flag_Pending = 0;
static unsigned char Flag_Announcing = 0;

//Motor Transmission timeout
static unsigned char Timer_Motors;
static unsigned char TimerFlag_Motors = 1;

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

/*------------------- Init Functions --------------------*/

/**********************************************************
Function:   InitMain
Parameters: none
Returns:    none
Description:
    Clears Analog select registers, sets up debug ports
**********************************************************/
static void InitMain(void){
    //Clear ANSEL registers
	ANSEL = 0;
	ANSELH = 0;

    PORTC = 0b00010000;
    //state indicators
    TRISC0 = 0;
    TRISC1 = 0;
    TRISC2 = 0;
    TRISA2 = 0;
}

/**********************************************************
Function:   InitTimer2
Parameters: none
Returns:    none
Description:
    Initializes timeout timer to 76Hz
**********************************************************/
static void InitTimer2(void){
    TMR2IF = 0; //reset timer flag
    TMR2 = 0; //reset timer
    PR2 = 255; //76Hz with 1:16 pre and postscale
    T2CON = 0b01111111; //T2 on with 1:16 pre and postscale
}

/**********************************************************
Function:   InitMotors
Parameters: none
Returns:    none
Description:
    Initializes motors to stopped states
**********************************************************/
static void InitMotors(void){
    CreateMotorTransmission(Servo_None, Motor_Stop, Motor_Stop);
}


/*------------------ Update Functions -------------------*/

/**********************************************************
Function:   UpdateTimer2
Parameters: none
Returns:    none
Description:
    Updates all state timers on a new timer2 overflow.
	Sets flags if timers expire.
**********************************************************/
static void UpdateTimer2(void){
    if (TMR2IF == 1){
        TMR2IF = 0;

        //Timer variable --;
        //If = 0, set flag

        Timer_Listening--;
        if (Timer_Listening == 0){
            TimerFlag_Listening = 1;
        }

        Timer_Confirming--;
        if (Timer_Confirming == 0){
            TimerFlag_Confirming = 1;
        }

        Timer_Flags--;
        if (Timer_Flags == 0){
            TimerFlag_Flags = 1;
        }

        Timer_Capturing--;
        if (Timer_Capturing == 0){
            TimerFlag_Capturing = 1;
        }

        Timer_Pending--;
        if (Timer_Pending == 0){
            TimerFlag_Pending = 1;
        }

        Timer_Announcing--;
        if (Timer_Announcing == 0){
            TimerFlag_Announcing = 1;
        }

        Timer_Motors--;
        if (Timer_Motors == 0){
            TimerFlag_Motors = 1;
        }
    }
}

/**********************************************************
Function:   UpdateMotors
Parameters: none
Returns:    none
Description:
    Updates motors based on new transmission from CVC.
	If no transmission from CVC for 1 second, stops motors.
**********************************************************/
static void UpdateMotors(void){
    //If new message was received
	if (NewXbeeMessageFlag == 1){
		//Check to see if it was a command from the CVC
        if ((ReadXbeeMessage(Byte_API) == API_Receive) &&
		    (ReadXbeeMessage(Byte_AddressHigh) == Address_CVCHigh) &&
			(ReadXbeeMessage(Byte_AddressLow) == Address_CVCLow) &&
            ((ReadXbeeMessage(Byte_MessageType) & MessageTypeMask) == MessageType_Direct) &&
            ((ReadXbeeMessage(Byte_Command) == Command_C2B) ||
             (ReadXbeeMessage(Byte_Command) == Start_Motor))){
			//If we aren't during team setup
            if ((MainState != Main_Listening) &&
                (MainState != Main_Confirming) &&
                (MainState != Main_Seeking) &&
                (MainState != Main_Timeout)){

				//Add team flag signal to ServosByte
                unsigned char ServosByte;
                ServosByte = (ReadXbeeMessage(Byte_Servos) | MyFlag);

				//Update output port for god mode
                RC1 = ((ReadXbeeMessage(Byte_Servos) & BIT7HI) == BIT7HI);

				//Send data to motors
                CreateMotorTransmission(ServosByte, ReadXbeeMessage(Byte_Motor0), ReadXbeeMessage(Byte_Motor1));

                //Reset Motor Timeout
                Timer_Motors = 76;
                TimerFlag_Motors = 0;
            }
        }
    }

    //If timed out, stop motors
    if ((TimerFlag_Motors == 1) && (MainState != Main_Timeout)){
		//Reset Motor Timeout
        Timer_Motors = 76;
        TimerFlag_Motors = 0;

    	//Kill god mode
        RC1 = 0;

		//Stop motors, with flag still raised.
        CreateMotorTransmission(MyFlag, Motor_Stop, Motor_Stop);
    }
}


/**********************************************************
Function:   UpdateMainStateMachine
Parameters: none
Returns:    none
Description:
    Updates team finding and atoll capturing state machine
	based on SPI and Xbee received messages.  Event
	checking is all performed locally, within each state.
**********************************************************/
static void UpdateMainStateMachine(void){

    /* Overriding state transitions on color card scan */
    if (NewSPIColorFlag == 1){
        //Find Card Color
        CardColor = IdentifyColor(ReadSPIMessage(Byte_S1),ReadSPIMessage(Byte_S2),ReadSPIMessage(Byte_S3));

        if (CardColor != Team_Error){
            //Lower team flags
            MyFlag = Servo_None;
            CreateMotorTransmission(MyFlag, Motor_Stop, Motor_Stop);

            if (CardColor == Team_None){
                //Clear team color
                MyTeam = Team_None;
                //set state to Idle
                MainState = Main_Idle;
            }
            else { //card color is red or green
                //Set Pending team color
                if (CardColor == Team_Red){
                    MyTeam = Team_RedPending;
                }
                else{ //CardColor == Team_Green)
                    MyTeam = Team_GreenPending;
                }
                //set state to listening
                MainState = Main_Listening;
                //start 1s timer
                Timer_Listening = 76;
                TimerFlag_Listening = 0;
            }

            //Tell CVC new or pending color
            StartXbeeTransmission(FrameID_NoAck, Address_CVCHigh, Address_CVCLow);
            AddTransmissionData(Command_B2C);
            AddTransmissionData(MyTeam);
            FinishXbeeTransmission();
        }
    }

    /* If there was no color scan, run normal state machine */
    else{
        switch (MainState){

            /* State: Idle */
            case Main_Idle:

                //If we scan an atoll card
                if (NewSPIAtollFlag == 1){

                    //Get Atoll data
                    Atoll_S1 = ReadSPIMessage(Byte_S1);
                    Atoll_S2 = ReadSPIMessage(Byte_S2);
                    Atoll_S3 = ReadSPIMessage(Byte_S3);
                    Atoll_SK1 = ReadSPIMessage(Byte_SK1);
                    Atoll_SK2 = ReadSPIMessage(Byte_SK2);
                    Atoll_SK3 = ReadSPIMessage(Byte_SK3);
                    AtollNumber = IdentifyAtoll(Atoll_S1, Atoll_S2, Atoll_S3);

                    if (AtollNumber != Atoll_Error){
                        //enter capturing state
                        MainState = Main_Capturing;

                        //Capturing state initialization
                        Flag_Capturing = 1;     //Set flag to send capture request
                        Counter_Capturing = 0;  //clear counter of number of capture requests
                        Counter_Pending = 0;    //clear counter of atoll responses
                        FrameID_Capturing += 8; //Add 2^n so never hits 0.
                    }
                }

                //If we happen to receive a random capture success message, why not use it:
                else if (NewXbeeMessageFlag == 1){
                    if ((ReadXbeeMessage(Byte_API) == API_Receive) &&
                        ((ReadXbeeMessage(Byte_MessageType) & MessageTypeMask) == MessageType_Direct) &&
                        (ReadXbeeMessage(Byte_Command) == Command_Reply) &&
                        (ReadXbeeMessage(Byte_Reply) == Reply_Success) &&
                        (ReadXbeeMessage(Byte_NewOwner) == MyTeam)){

                        //Set atoll to claim
                        AtollNumber = ReadXbeeMessage(Byte_Atoll);

                        //enter announcing state
                        MainState = Main_Announcing;

                        //Announcing State initialization
                        Flag_Announcing = 1;        //OK to send announcement
                        Timer_Announcing = 76;      //Set timer for broadcast success
                        TimerFlag_Announcing = 0;   //Clear timer flag
                        Counter_Announcing = 0;     //Clear counter of announcements
                        FrameID_Announcing += 8;    //Add 2^n so never hits 0.
                    }
                }
                break;

            /* State: Listening for Teammate */
            case Main_Listening:
                //If we hear from our teammate:
                if (NewXbeeMessageFlag == 1){
                    if ((ReadXbeeMessage(Byte_API) == API_Receive) &&
                        (ReadXbeeMessage(Byte_Command) == Command_FindTeam) &&
                        (ReadXbeeMessage(Byte_Team) == CardColor)){

                        //Store teammate address
                        Address_TeammateHigh = ReadXbeeMessage(Byte_AddressHigh);
                        Address_TeammateLow = ReadXbeeMessage(Byte_AddressLow);

                        //enter confirming state
                        MainState = Main_Confirming;

                        //Confirming State initialization
                        Counter_Confirming = 0;     //Clear counter of confirmation attempts
                        FrameID_Confirming += 8;    //Add 2^n so never hits 0.
                    }
                }

                //If we haven't heard from our teammate for 1 second, assume we are first boat
                else if (TimerFlag_Listening == 1){
                    //enter seeking state
                    MainState = Main_Seeking;

                    //Seeking state initialization
                    Counter_Seeking = 0;        //Clear counter of teammate finding broadcasts
                    FrameID_Seeking += 8;       //Add 2^n so never hits 0.
                }
                break;

            /* State: Confirming Team */
            case Main_Confirming:

                // If we receive an ACK from our Xbee of our confirmation message
                if (NewXbeeMessageFlag == 1){
                    if ((ReadXbeeMessage(Byte_API) == API_Status) &&
                        (ReadXbeeMessage(Byte_FrameID) == FrameID_Confirming)){
                        if (ReadXbeeMessage(Byte_Status) == Status_Success){
                            //set team
                            MyTeam = CardColor;
                            if (CardColor == Team_Red){
                                MyFlag = Servo_Red;
                            } else {
                                MyFlag = Servo_Green;
                            }

                            //raise flag
                            CreateMotorTransmission(MyFlag, Motor_Stop, Motor_Stop);

                            //Tell CVC new color
                            StartXbeeTransmission(FrameID_NoAck, Address_CVCHigh, Address_CVCLow);
                            AddTransmissionData(Command_B2C);
                            AddTransmissionData(MyTeam);
                            FinishXbeeTransmission();

                            //return to idle
                            MainState = Main_Idle;
                        }
                    }
                }

                // If we haven't received an ACK
                else if (CheckXbeeTransmitOK() == 1){
                    //Increase Counter of confirmation messages
                    Counter_Confirming++;

                    //If we have tried 10 times
                    if (Counter_Confirming >= 10){
                        //go to timeout
                        MainState = Main_Timeout;
                        MyTeam = CardColor;
                        if (CardColor == Team_Red){
                            MyFlag = Servo_Red;
                        } else {
                            MyFlag = Servo_Green;
                        }

                        //Timeout state initialization
                        TimerFlag_Flags = 1;
                        Counter_Flags = 0;
                    }

                    //If we haven't yet tried 10 times
                    else {
                        // send team confirmation
                        StartXbeeTransmission(FrameID_Confirming, Address_TeammateHigh, Address_TeammateLow);
                        AddTransmissionData(Command_FindTeam);
                        AddTransmissionData(CardColor);
                        FinishXbeeTransmission();
                    }
                }
                break;

            /* State: Seeking Teammate */
            case Main_Seeking:
                //If reply received from teammate
                if (NewXbeeMessageFlag == 1){
                     if ((ReadXbeeMessage(Byte_API) == API_Receive) &&
                        (ReadXbeeMessage(Byte_Command) == Command_FindTeam) &&
                        (ReadXbeeMessage(Byte_Team) == CardColor)){
                        if ((ReadXbeeMessage(Byte_MessageType) & MessageTypeMask) == MessageType_Direct){
                            //set team
                            MyTeam = CardColor;
                            if (CardColor == Team_Red){
                                MyFlag = Servo_Red;
                            } else {
                                MyFlag = Servo_Green;
                            }

                            //raise flag
                            CreateMotorTransmission(MyFlag, Motor_Stop, Motor_Stop);

                            //Tell CVC new color
                            StartXbeeTransmission(FrameID_NoAck, Address_CVCHigh, Address_CVCLow);
                            AddTransmissionData(Command_B2C);
                            AddTransmissionData(MyTeam);
                            FinishXbeeTransmission();

                            //return to idle
                            MainState = Main_Idle;
                        }

                        // If it wasn't a direct message
                        else {
                            //another team is broadcasting.  what do we do?
                        }
                    }
                }

                //If we haven't received a reply from our teammate, broadcast again
                else if (CheckXbeeTransmitOK() == 1){
                    //Increase count of broadcasts
                    Counter_Seeking++;

                    //If we have broadcasted 255 times,
                    if (Counter_Seeking >= 255){ //should be 255
                        //go to timeout
                        MainState = Main_Timeout;
                        MyTeam = CardColor;
                        if (CardColor == Team_Red){
                            MyFlag = Servo_Red;
                        } else {
                            MyFlag = Servo_Green;
                        }

                        //Timeout state initialization
                        TimerFlag_Flags = 1;
                        Counter_Flags = 0;
                    }

                    //If we haven't yet broadcast 255 times
                    else {
                        //resend find teammate broadcast
                        StartXbeeTransmission(FrameID_Seeking, Address_BroadcastHigh, Address_BroadcastLow);
                        AddTransmissionData(Command_FindTeam);
                        AddTransmissionData(CardColor);
                        FinishXbeeTransmission();
                    }
                }
                break;


            /* State: Timing Out of Team Finding */
            case Main_Timeout:
                //If timer has expired, telling us to switch flag that is showing
                if (TimerFlag_Flags == 1 ){
                    //Reset timer
                    TimerFlag_Flags = 0;
                    Timer_Flags = 38;

                    //Increase count of flag flashings
                    Counter_Flags ++;

                    //If we have flashed our flags 20 times (10 seconds)
                    if (Counter_Flags >= 20){
                        //raise flag
                        CreateMotorTransmission(MyFlag, Motor_Stop, Motor_Stop);

                        //Tell CVC new color
                        StartXbeeTransmission(FrameID_NoAck, Address_CVCHigh, Address_CVCLow);
                        AddTransmissionData(Command_B2C);
                        AddTransmissionData(MyTeam);
                        FinishXbeeTransmission();

                        //return to idle
                        MainState = Main_Idle;
                    }

                    //If we haven't yet flashed our flags 20 times
                    else {
                        //Switch flags state
                        CreateMotorTransmission(TimeoutServos[Counter_Flags % 2] , Motor_Stop, Motor_Stop);
                    }
                }
                break;

            /* State: Broadcasting Capture Request */
            case Main_Capturing:
                //If timer has expired (without an ACK)
                if (TimerFlag_Capturing == 1){
                    //Set flag to send new request
                    Flag_Capturing = 1;
                }

                //If a transmit status is received for our capture request
                if (NewXbeeMessageFlag == 1){
                    if ((ReadXbeeMessage(Byte_API) == API_Status) &&
                        (ReadXbeeMessage(Byte_FrameID) == FrameID_Capturing)){
                        //if it was an ACK
                        if (ReadXbeeMessage(Byte_Status) == Status_Success){
                            //enter pending state
                            MainState = Main_Pending;

                            //Pending State initialization
                            Flag_Pending = 0;       //Clear failure flag
                            Timer_Pending = 38;     //start state timer
                            TimerFlag_Pending = 0;  //clear state timer flag
                        }

                        //if it was not an ACK, message failed
                        else {
                            //Set flag to send new request
                            Flag_Capturing = 1;
                        }
                    }
                }

                //If we are to request again
                else if ((Flag_Capturing == 1) && (CheckXbeeTransmitOK() == 1)){
                    //Reset Timers and Flags
                    Flag_Capturing = 0;         //Clear failure flag
                    Timer_Capturing = 38;       //Reset state timer
                    TimerFlag_Capturing = 0;    //Clear timeout flag

                    //Increase capture request count
                    Counter_Capturing++;

                    //If we have requested a capture 3 times
                    if (Counter_Capturing >= 3){
                        // return to idle
                        MainState = Main_Idle;
                    }

                    //If we have yet to request a capture 3 times
                    else {
                        //resend capture request
                        StartXbeeTransmission(FrameID_Capturing, Address_BroadcastHigh, Address_BroadcastLow);
                        AddTransmissionData(Command_Capture);
                        AddTransmissionData(MyTeam);
                        AddTransmissionData(AtollNumber);
                        AddTransmissionData(Atoll_S1);
                        AddTransmissionData(Atoll_S2);
                        AddTransmissionData(Atoll_S3);
                        AddTransmissionData(Atoll_SK1);
                        AddTransmissionData(Atoll_SK2);
                        AddTransmissionData(Atoll_SK3);
                        FinishXbeeTransmission();
                    }
                }
                break;

            /* State: Capture Request Pending */
            case Main_Pending:
                //If timer has expired without a response
                if (TimerFlag_Pending == 1){
                    //Set flag to return to Capture Request state
                    Flag_Pending = 1;
                }

                //If we have received a response from the Atoll
                if (NewXbeeMessageFlag == 1){
                    if ((ReadXbeeMessage(Byte_API) == API_Receive) &&
                        ((ReadXbeeMessage(Byte_MessageType) & MessageTypeMask) == MessageType_Direct) &&
                        (ReadXbeeMessage(Byte_Command) == Command_Reply)){

                        //If the message was for a successful capture
                        if ((ReadXbeeMessage(Byte_Reply) == Reply_Success) &&
                            (ReadXbeeMessage(Byte_NewOwner) == MyTeam)){

                            //Set atoll to claim, since hey, we don't care if it's not the one we asked for
                            AtollNumber = ReadXbeeMessage(Byte_Atoll);

                            //enter announcing state
                            MainState = Main_Announcing;

                            //Announcing State initialization
                            Flag_Announcing = 1;        //OK to send announcement
                            Timer_Announcing = 76;      //Set timer for broadcast success
                            TimerFlag_Announcing = 0;   //Clear timer flag
                            Counter_Announcing = 0;     //Clear counter of announcements
                            FrameID_Announcing += 8;    //Add 2^n so never hits 0.
                        }

                        //If the message was not a successful capture
                        else {
                            //Set flag to return to capture request state
                            Flag_Pending = 1;
                        }
                    }

                }

                //If we don't have a response but have timed out or failed
                else if ( Flag_Pending == 1 ){
                    //Increase count of overall capture attempts
                    Counter_Pending ++;

                    //If that was our second failure
                    if (Counter_Pending >= 2){
                        //return to idle.  do not pass go.  do not collect $200.
                        MainState = Main_Idle;
                    }

                    //If that was only our first failure
                    else{
                        //reenter capturing state
                        MainState = Main_Capturing;

                        //Capturing state initialization
                        Flag_Capturing = 1;     //Set flag to send capture request
                        Counter_Capturing = 0;  //clear counter of number of capture requests
                        FrameID_Capturing += 8; //Add 2^n so never hits 0.
                    }
                }
                break;

            /* State: Announcing an Atoll Capture */
            case Main_Announcing:
                //If we have a transmit status for our capture attempt
                if (NewXbeeMessageFlag == 1){
                    if ((ReadXbeeMessage(Byte_API) == API_Status) &&
                        (ReadXbeeMessage(Byte_FrameID) == FrameID_Announcing)){
                        if (ReadXbeeMessage(Byte_Status) == Status_Success){
                            //if successful broadcast, send a new one
                            Flag_Announcing = 1;
                            //Increase broadcast counter
                            Counter_Announcing++;

                            //Reset state timer
                            Timer_Announcing = 76;
                            TimerFlag_Announcing = 0;
                        }
                    }
                }

                //If state timer expires without transmit status
                if (TimerFlag_Announcing == 1){
                    //send new broadcast anyway
                    Flag_Announcing = 1;
                    //Increase broadcast counter
                    Counter_Announcing++;

                    //Reset state timer
                    Timer_Announcing = 76;
                    TimerFlag_Announcing = 0;
                }

                //If we are able to announce again
                if ((CheckXbeeTransmitOK() == 1) && (Flag_Announcing == 1)){
                    //Reset Flag
                    Flag_Announcing = 0;

                    //Reset state timer
                    Timer_Announcing = 76;
                    TimerFlag_Announcing = 0;

                    //If we have already sent two announcements
                    if (Counter_Announcing >= 2){
                        //return to idle, victorious
                        MainState = Main_Idle;
                    }

                    //If we have not yet sent two announcements
                    else {
                        //send announcement
                        StartXbeeTransmission(FrameID_Announcing, Address_BroadcastHigh, Address_BroadcastLow);
                        AddTransmissionData(Command_Announce);
                        AddTransmissionData(MyTeam);
                        AddTransmissionData(AtollNumber);
                        FinishXbeeTransmission();
                    }
                }
                break;
        }
    }
}

/*------------- Main and Helper Functions ---------------*/

/**********************************************************
Function:   Main
Parameters: none
Returns:    none
Description:
    Runs initialization and update functions.
**********************************************************/
#ifndef UARTdebug
void main(void){
	//Run initialization functions
    InitMain();
    InitTimer0();
    InitUART();
    InitSPI();
    InitTimer2();
    InitMotors();

	//Main loop
    while(1){
		//Run communication update functions
        UpdateUART();
        UpdateSPI();

		//update timeout timer
        UpdateTimer2();

		//Check for new xbee message
        NewXbeeMessageFlag = 0;
        if (CheckReceiveMessageFlag() == 1){
            NewXbeeMessageFlag = 1;
        }

		//Check for new card scan message
        NewSPIAtollFlag = 0;
        NewSPIColorFlag = 0;
        if (CheckSPIMessageFlag() > 0){
            if (ReadSPIMessage(Byte_CardType) == Start_Atoll){
				//If message was for an atoll scan
                NewSPIAtollFlag = 1;
            }
            else if (ReadSPIMessage(Byte_CardType) == Start_Color){
				//if message was for a color scan
                NewSPIColorFlag = 1;
            }
        }

		//Run motor update function
        UpdateMotors();

		//update team finding and atoll capture state machine
        UpdateMainStateMachine();
        RC2 = (MainState > 1);	//Debug output LED.  Gives slight indicator of state.

		//Set debug output LEDs based on team state
        switch (MyTeam){
            case Team_Green:
                RC0 = 0;
                RA2 = 1;
                break;
            case Team_Red:
                RC0 = 1;
                RA2 = 0;
                break;
            default:
                RC0 = 0;
                RA2 = 0;
                break;
        }
    }
}
#endif

/**********************************************************
Function:   IdentifyColor
Parameters: unsigned chars S1, S2, S3 (serial numbers)
Returns:    unsigned char - the team color of a scanned
							card, or Team_Error if none
Description:
    Looks up the scanned color serial numbers in the
	ColorLookup array.  Returns the matching color, if any.
	Otherwise returns Team_Error.
**********************************************************/
static unsigned char IdentifyColor(unsigned char S1, unsigned char S2, unsigned char S3){
    unsigned char i = 0;
    for (i = 0; i < 3; i++){
        if ((S1 == ColorLookup[i][1]) && (S2 == ColorLookup[i][2]) && (S3 == ColorLookup[i][3])){
            return ColorLookup[i][0]; //If we find the color, return it
        }
    }
    return Team_Error;
}

/**********************************************************
Function:   IdentifyAtoll
Parameters: unsigned chars S1, S2, S3 (serial numbers)
Returns:    unsigned char - the atoll number of a scanned
							card, or Atoll_Error if none
Description:
    Looks up the scanned color serial numbers in the
	AtollLookup array.  Returns the matching atoll, if any.
	Otherwise returns Atoll_Error.
**********************************************************/
static unsigned char IdentifyAtoll(unsigned char S1, unsigned char S2, unsigned char S3){
    unsigned char i = 0;
    for (i = 0; i < 10; i++){
        if ((S1 == AtollLookup[i][1]) && (S2 == AtollLookup[i][2]) && (S3 == AtollLookup[i][3])){
            return AtollLookup[i][0]; //if we find the atoll, return it
        }
    }
    return Atoll_Error;
}