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

__CONFIG(CP_OFF & WDTE_OFF & PWRTE_ON & FOSC_HS);

/*------------------- Module Defines --------------------*/
#define FireBit0 RC0
#define SelectBit0 RC1
#define SelectBit1 RA2
#define PowerBit RA1

#define LEDPin RC7

#define StatusPin RC5

/*------------------ Module Functions -------------------*/
static void SpoofInit(void);
static void UARTInit(void);

static void SpoofRFID(unsigned char AtollNumber);
static void SpoofRFIDColor(unsigned char Color);

static void Pause(void);

/*------------------ Module Variables -------------------*/
static unsigned char FireFlag = 0;
static unsigned char Index = 0;
static unsigned char Counter2 = 0;

//Atoll Card ASCII Messages
static unsigned char Atoll[5][14] = {
//02 | hidden bytes 16 and 0 |   Byte 1  |   Byte 2  |   Byte 3  |  Checksum |  03
{0x02, 0x31, 0x36, 0x30, 0x30, 0x35, 0x45, 0x36, 0x46, 0x34, 0x37, 0x36, 0x30, 0x03},  //Atoll 1
{0x02, 0x31, 0x36, 0x30, 0x30, 0x38, 0x33, 0x43, 0x46, 0x43, 0x38, 0x39, 0x32, 0x03},  //Atoll 2
{0x02, 0x31, 0x36, 0x30, 0x30, 0x38, 0x33, 0x43, 0x37, 0x33, 0x36, 0x36, 0x34, 0x03},  //Atoll 3
{0x02, 0x31, 0x36, 0x30, 0x30, 0x38, 0x33, 0x45, 0x30, 0x46, 0x35, 0x38, 0x30, 0x03},  //Atoll 4
{0x02, 0x31, 0x36, 0x30, 0x30, 0x38, 0x34, 0x30, 0x38, 0x35, 0x45, 0x43, 0x34, 0x03}  //Atoll 5
};

//Color Card ASCII Messages
static unsigned char Team[3][14] = {
//02 | hidden bytes 16 and 0 |   Byte 1  |   Byte 2  |   Byte 3  |  Checksum |  03
{0x02, 0x33, 0x42, 0x30, 0x30, 0x33, 0x32, 0x39, 0x45, 0x30, 0x36, 0x39, 0x31, 0x03}, //None
{0x02, 0x33, 0x42, 0x30, 0x30, 0x33, 0x35, 0x44, 0x35, 0x45, 0x43, 0x33, 0x37, 0x03}, //Red
{0x02, 0x33, 0x42, 0x30, 0x30, 0x33, 0x35, 0x39, 0x43, 0x35, 0x41, 0x43, 0x38, 0x03}  //Green
};


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

/**********************************************************
Function:   UARTInit
Parameters: none
Returns:    none
Description:
    Initializes UART to 9600,N,8,1
**********************************************************/
static void UARTInit(void){
	//TRIS registers for UART
	TRISB5 = 1; //RX input
	TRISB7 = 0; //TX output

    //9600 baud rate:
    SPBRG = 129;
    BRGH = 1;
    //asynch mode:
    SYNC = 0;
    SPEN = 1;
    //enable tx and rx:
    TXEN = 1;
	CREN = 1;
}

/**********************************************************
Function:   SpoofInit
Parameters: none
Returns:    none
Description:
    General Initialization for module
**********************************************************/
static void SpoofInit(void){
	//Clear ANSEL registers
	ANSEL = 0;
	ANSELH = 0;

    //Timer2 Init for timing
    PR2 = 55; //2.8ms per overflow
    T2CON = 0b11111111;
          //  x0000xxx    1:1 postscale
          //  xxxxx1xx    TMR2 on
          //  xxxxxx11    1:16 prescale

    //Fire and select Pins inputs
    TRISC0 = 1;
    TRISC1 = 1;
    TRISA2 = 1;

	//Select pins power output
    PowerBit = 1;
    TRISA1 = 0;

    //Spoof Outputs
    LEDPin = 0;
    TRISC7 = 0;

	//Status output
    StatusPin = 1;
    TRISC5 = 0;
}

/**********************************************************
Function:   main
Parameters: none
Returns:    none
Description:
    Calls initialization functions, then enters loop.  Loop
	checks for new fire event.  In the case of a new fire
	event, the loop executes the desired fake scans as
	determined by the select pins.
**********************************************************/
void main(void){
    SpoofInit();
    UARTInit();

    while(1){
        //Reset Flag if trigger is low
        if ((FireBit0 == 0)){
            FireFlag = 0;
        }

		//If new trigger event
        if ((FireBit0 == 1) && (FireFlag == 0)){
            FireFlag = 1; //set flag

			//Determine desired scan
            if (SelectBit0 == 0){
                if (SelectBit1 == 0){
				//Low, Low = White card scan
                    StatusPin = 0;
                    SpoofRFIDColor(0);//None
                    Pause();
                    Pause();
                    StatusPin = 1;
                }else{
				//Low, High = Red card scan
                    StatusPin = 0;
                    SpoofRFIDColor(1);//Red
                    Pause();
                    Pause();
                    StatusPin = 1;
                }
            }else{
                if (SelectBit1 == 0){
                //High, Low = Green card scan
				    StatusPin = 0;
                    SpoofRFIDColor(2);//Green
                    Pause();
                    Pause();
                    StatusPin = 1;
                }else{
				//High, High = Capture all atolls
                    StatusPin = 0;
                    SpoofRFID(0); //Atoll 1
                    Pause();
                    Pause();
                    SpoofRFID(1); //Atoll 2
                    Pause();
                    Pause();
                    SpoofRFID(2); //Atoll 3
                    Pause();
                    Pause();
                    SpoofRFID(3); //Atoll 4
                    Pause();
                    Pause();
                    SpoofRFID(4); //Atoll 5
                    Pause();
                    Pause();
                    StatusPin = 1;
                }
            }
        }
    }

}

/**********************************************************
Function:   SpoofRFID
Parameters: unsigned char AtollNumber (actually AN-1)
Returns:    none
Description:
    Sends out the required signals to spoof the Security
	Controller and our own RFID PIC into thinking an atoll
	card was scanned.
**********************************************************/
static void SpoofRFID(unsigned char AtollNumber){
    TMR2 = 0;		//clear timer
    TMR2IF = 0;		//clear timer flag
    LEDPin = 1;     //set LED bit
    Counter2 = 0;	//reset counter
    Index = 0;		//reset serial number index
    while (Counter2 < 56){	//loop for 160ms = LED line on time
        if (TMR2IF == 1){ 	//if timer 2 overflows
            TMR2IF = 0;
            Counter2 ++;	//increment counter
        }

		// Starting at 11ms, send out the atoll serial bytes
        if ((Index < 14) && (Counter2 >= 4) && (TXIF == 1)){
            TXREG = Atoll[AtollNumber][Index];	//send next byte
            Index++;	//increment index
        }
    }
    LEDPin = 0; //clear LED bit
}

/**********************************************************
Function:   SpoofRFIDColor
Parameters: unsigned char Color (None = 0, Red = 1, Green = 2)
Returns:    none
Description:
    Sends out the required signals to spoof the Security
	Controller and our own RFID PIC into thinking an atoll
	card was scanned.
**********************************************************/
static void SpoofRFIDColor(unsigned char Color){
    TMR2 = 0;		//clear timer
    TMR2IF = 0;		//clear timer flag
    LEDPin = 1;     //set LED bit
    Counter2 = 0;	//reset counter
    Index = 0;		//reset serial number index
    while (Counter2 < 56){	//loop for 160ms = LED line on time
        if (TMR2IF == 1){ 	//if timer 2 overflows
            TMR2IF = 0;
            Counter2 ++;	//increment counter
        }

		// Starting at 11ms, send out the card serial bytes
        if ((Index < 14) && (Counter2 >= 4) && (TXIF == 1)){
            TXREG = Team[Color][Index]; 	//send next byte
            Index++;	//increment index
        }
    }
    LEDPin = 0; //clear LED bit
}

/**********************************************************
Function:   Pause
Parameters: none
Returns:    none
Description:
    Does a blocking pause to separate the time between fake
	scans.  Blocking is OK since this chip has one function
	and doesn't need to remember missed input events.
**********************************************************/
static void Pause(void){
    TMR2 = 0;
    TMR2IF = 0;
    Counter2 = 0;
    while (Counter2 < 255){
        if (TMR2IF == 1){ //if timer 2 overflows
            TMR2IF = 0;
            Counter2 ++;
        }
    }
}