#include <htc.h> #include "pic16f690.h" #include <stdio.h> #include "bitdefs.h" __CONFIG(CP_OFF & WDTE_OFF & PWRTE_ON & FOSC_HS); /*------------------- Module Defines --------------------*/ // Port Definitions #define RFID_RequestBit RC3 #define SS_RFID RC6 #define SS_Xbee RC4 #define DebugBit RC0 // Transmission Bytes #define RFID_DummyByte 0xB9 #define Start_Color 0xCC #define Start_Atoll 0xAA // State Machine States typedef enum { Security_Idle = 0, Security_RFID, Security_SC, Security_Xbee } SecurityState_t; /*------------------ Module Functions -------------------*/ static void SPIInit(void); static void SecurityInit(void); static void UpdateTimer(void); static unsigned char CheckRFIDColor(void); /*------------------ Module Variables -------------------*/ // State Machine Variables static SecurityState_t SecurityState = Security_Idle; static unsigned char StateTimer = 0; // Transmission Variables static unsigned char RFIDColorFlag = 0; static unsigned char RFID_Index = 0; static unsigned char Xbee_Index = 0; static unsigned char RFID_Data[5]; static unsigned char Xbee_Data[10]; /*-------------------- Module Code ----------------------*/ /********************************************************** Function: UARTInit Parameters: none Returns: none Description: Initializes UART to 9600,N,8,1 **********************************************************/ 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: SPIInit Parameters: none Returns: none Description: Initializes SPI as Master, timed by Timer 2 **********************************************************/ static void SPIInit(void){ //Deselect both slaves initially SS_RFID = 1; SS_Xbee = 1; //TRIS registers for SPI TRISC7 = 0; //SDO output TRISB6 = 0; //clock output TRISB4 = 1; //SDI input TRISC6 = 0; //RFID SS output TRISC4 = 0; //Xbee SS output TRISC3 = 1; //RFID ready input //Configure SPI Status register SSPSTAT = 0b00000000; // 0xxxxxxx Input data sampled at middle of ouput time // x0xxxxxx CKE - Data transmitted on rising edge of SCK //setup SPI Control register SSPCON = 0b00110011; // xx1xxxxx Enables SPI // xxx1xxxx CKP - clock idles high // xxxx0011 SPI master, clock = TMR2 output / 2 } /********************************************************** Function: SecurityInit Parameters: none Returns: none Description: General initialization for this module, including timer initialization. **********************************************************/ static void SecurityInit(void){ //Clear ANSEL registers ANSEL = 0; ANSELH = 0; //Timer0 Init (overflows at 76 Hz) T0CS = 0; //use Fosc/4 PSA = 0; //prescale for T0 PS0 = 1; //Set Prescale to 256. PS1 = 1; PS2 = 1; //Timer2 Init for SPI PR2 = 125; //10kHz SPI rate, with 1:4 prescale below T2CON = 0b00000101; // x0000xxx 1:1 postscale // xxxxx1xx TMR2 on // xxxxxx01 1:4 prescale //Debug Pin DebugBit = 1; TRISC0 = 0; //debug LED output } /********************************************************** Function: main Parameters: none Returns: none Description: Calls initialization functions, then enters state machine loop. State machine consists of a switch on the current state, at which point the relevant events are checked (equivalent to local event checkers). Only one state is called per loop and only one state transmission is feasible per loop. **********************************************************/ void main(void){ SecurityInit(); UARTInit(); SPIInit(); while(1){ UpdateTimer(); switch (SecurityState){ // State: Idle case Security_Idle: // Event: RFID PIC has new data to send if (RFID_RequestBit == 1){ SS_Xbee = 1; //ensure Xbee slave deselected SS_RFID = 0; //select RFID slave RFID_Index = 0; //reset byte counter SSPBUF = RFID_DummyByte; //Start transmission SecurityState = Security_RFID; //change states StateTimer = 0; } break; // State: Reading from RFID PIC case Security_RFID: // Event: New byte received over SPI if (SSPIF == 1){ SSPIF = 0; //clear SPI flag //store byte for transmission to SC: RFID_Data[RFID_Index] = SSPBUF; //store byte for transmission to Xbee PIC: Xbee_Data[RFID_Index] = RFID_Data[RFID_Index]; RFID_Index++; //increment index // make sure index doesn't leave array: RFID_Index = ((RFID_Index > 4) ? 4 : RFID_Index); //If there is more data to send (request line still high) if (RFID_RequestBit == 1){ SSPBUF = RFID_DummyByte; //get next byte StateTimer = 0; } //Otherwise, no more data else{ SS_RFID = 0; //deselect RFID slave RFID_Data[0] = 0x04; //start and end bytes for SC message RFID_Data[4] = 0x08; SS_RFID = 1; //Ensure RFID slave deselected if (CheckRFIDColor() == 1){ //If card was a color card SS_Xbee = 0; //Select Xbee slave RFIDColorFlag = 1; RFID_Index = 1; //include header byte below Xbee_Index = 1; //include header byte below SSPIF = 0; SSPBUF = Start_Color; //Xbee_Header; SecurityState = Security_Xbee; //send direct to xbee StateTimer = 0; } else { //If card was not a color card RFIDColorFlag = 0; RFID_Index = 0; //start at 0 to include header byte Xbee_Index = 4; //start at 4 for SC data SecurityState = Security_SC; //send to Security controller StateTimer = 0; } } } break; // State: Communicating with Security controller case Security_SC: //Event: Transmission of byte complete if ((TXIF == 1) && (RFID_Index <= 4)){ //Send next byte: TXREG = RFID_Data[RFID_Index]; RFID_Index++; StateTimer = 0; } //Event: Received data from security controller if (RCIF == 1){ //Store data for transmission to Xbee PIC Xbee_Data[Xbee_Index] = RCREG; Xbee_Index++; StateTimer = 0; //If we have all the data from the SC, start xmit to Xbee PIC if (Xbee_Index == 10){ SS_RFID = 1; //Ensure RFID slave deselected SS_Xbee = 0; //Select Xbee slave Xbee_Index = 1; //start at 1 since header sent below RFID_Index = 1; SSPIF = 0; SSPBUF = Start_Atoll; //Send Xbee_Header; SecurityState = Security_Xbee; //change states } } break; // State: Communicating with Xbee PIC case Security_Xbee: //Event: Data received over SPI (i.e. byte sent) if (SSPIF == 1){ SSPIF = 0; //clear flag //If we have finished our transmission if (((Xbee_Index >= 4) && (RFIDColorFlag == 1)) || ((Xbee_Index >= 10) && (RFIDColorFlag == 0))){ //Deselect slaves: SS_RFID = 1; SS_Xbee = 1; //Reenter idle state: SecurityState = Security_Idle; StateTimer = 0; // Toggle debug bit DebugBit ^= 1; } //If we haven't finished our transmission else{ //Send next byte: SSPBUF = Xbee_Data[Xbee_Index]; //Increment Xbee data index if (Xbee_Index >= 4){ Xbee_Index++; //skip every other SC byte } Xbee_Index++; StateTimer = 0; } } break; } } } /********************************************************** Function: CheckRFIDColor Parameters: none Returns: unsigned char, 1 if card might be color card, 0 otherwise Description: Checks if the first byte of the serial number is less than 0x40, since all color cards and no atoll cards have this property. **********************************************************/ static unsigned char CheckRFIDColor(void){ return (RFID_Data[1] < 0x40); //since all color cards are less than 0x40 } /********************************************************** Function: UpdateTimer Parameters: none Returns: none Description: If timer0 has overflowed, the state timer is incremented. If it has overflowed 16 times (200ms) then the state machine is reset to Idle. **********************************************************/ static void UpdateTimer(void){ if (T0IF == 1){ //if timer 0 overflows T0IF = 0; StateTimer++; if (StateTimer >= 16){ StateTimer = 0; SecurityState = Security_Idle;//run reset function } } }