#define SECURITY_TEST /* Security PIC Module This module: (1) Takes an RFID message from the RFID PIC via SPI, converts ASCII->HEX (2) Prepares a message with the serial # for the security controller (3) Sends it via UART to the security controller (4) Receives a security key back via UART (5) Prepares a message with the serial # and security key for the Main PIC */ /* PINOUT FOR SECURITY CONTROLLER PIC ****************************************** 1 +5V |VDD VSS| GND 20 2 OSC1 |A5 A0| 19 3 OSC2 |A4 A1| 18 4 |A3 A2| 17 5 RFID_READY |C5 C0| SS-MAIN 16 6 |C4 C1| 15 7 |C3 C2| 14 8 SS-RFID |C6 B4| SPI-SDI 13 9 SPI-SDO |C7 B5| RX 12 10 TX |B7 B6| SPI-SCK 11 */ #include <htc.h> //#include "pic16f690.h" // for Eric's laptop #include <stdio.h> #define _LEGACY_HEADERS #include "BITDEFS.h" #include "TimerPIC.h" #define SS_RFID RC0 #define SS_MAIN RC6 #define DUMMY_BYTE 0xAA #define RFID_MESSAGE_LENGTH 14 #define RFID_HEX_LENGTH 6 #define SK_SEND_LENGTH 5 #define SK_RECEIVE_LENGTH 6 #define MAIN_SEND_LENGTH 6 #ifdef SECURITY_TEST __CONFIG(CP_OFF & WDTE_OFF & PWRTE_OFF & FOSC_HS); #endif typedef enum { WAITING_IDLE, WAITING_FOR_RFID, SENDING_TO_SECURITY_PIC, RECEIVING_FROM_SECURITY_PIC, SENDING_TO_MAIN_PIC } state_t; // Function prototypes void interrupt Security_ISR(void); void InitPins(void); void InitFlags(void); void InitSPI(void); void InitSCI(void); void InitInterrupts(void); void Init(void); void Update(void); unsigned char ConvertASCIItoHEX(unsigned char upper, unsigned char lower); unsigned char VerifyChecksum(void); void MakeSecurityMessage(void); void MakeMainMessage(void); // Module variables static unsigned char RFID_Ready; // Flag = set when RFID message available static unsigned char RFID_Message[RFID_MESSAGE_LENGTH]; // Incoming RFID message static unsigned char RFID_Hex[RFID_HEX_LENGTH]; // RFID data converted to HEX static unsigned char Security_TX[SK_SEND_LENGTH]; // Request to Security Controller static unsigned char Security_RX[SK_RECEIVE_LENGTH]; // Response from Security Controller static unsigned char Main_Message[MAIN_SEND_LENGTH]; // Message to Main PIC #ifdef SECURITY_TEST // Rising edge void interrupt Security_ISR(void) { // New RFID message ready if (CCP1IE && CCP1IF) { CCP1IF = 0; RFID_Ready = 1; } #endif void InitPins(void) { // Turn off analog inputs ANSEL = 0; ANSELH = 0; // Set C0 and C6 to be outputs (low) TRISC0 = 0; // SS (Main) TRISC6 = 0; // SS (RFID) TRISB6 = 0; // SCK TRISC7 = 0; // SDO TRISB7 = 0; // TX // Don't select either slave yet SS_RFID = 1; SS_MAIN = 1; } void InitFlags(void) { RFID_Ready = 0; } void InitSPI(void) { // Set up timer 2 for 19.53kHz TMR2ON = 1; // Prescaler = 1 T2CKPS0 = 0; T2CKPS1 = 0; // Configure SPI /* SPI port 0xxxxxxx = No write collision detect x0xxxxxx = No receive overflow indicator xx1xxxxx = Enable serial port, SCK, SDO, SDI as serial pins xxx1xxxx = Clock idles high xxxx0011 = SPI Master, clock = timer2 output/2 (about 10kHz) */ SSPCON = 0b00110011; /* SPI status register 0xxxxxxx = Data sampled in middle of output x0xxxxxx = Data transmitted on falling edge of SCK xxXXXXXX = Read only */ SSPSTAT = 0b00000000; SSPIE = 0; // Turn off SPI interrupt SSPBUF = 0; // Clear buffer } void InitSCI(void) { unsigned char temp; TXEN = 1; // Enable transmit SYNC = 0; // Turn off synchronous mode TX9 = 0; // Disable 9-bit transmission SPEN = 1; // Serial port enabled (configures RX/TX as serial port pins) CREN = 1; // Continuous receive RX9 = 0; // Disable 9-bit receive ADDEN = 0; // Turn off address detection BRGH = 1; // High data rate mode SPBRG = 0x81; // Set baud rate to 9600 SPBRGH = 0; // Clear high baud rate bits temp = RCREG; // Clear flag in case RCREG was full SSPIF = 0; // Clear before we can send over UART } void InitInterrupts(void) { // Capture on every rising edge // CCP1CON CCP1M0 = 1; CCP1M2 = 1; // Enable input capture CCP1IE = 1; // Enable Peripheral and Global Interrupts INTCON = 0; PEIE = 1; GIE = 1; } void Init(void) { InitPins(); InitFlags(); InitSPI(); InitSCI(); InitInterrupts(); } void Update(void) { static state_t currState = WAITING_IDLE; // Initial state static state_t nextState; static unsigned int counter = 0; // Initial counter // Assume we stay in the same state unless our SM says otherwise nextState = currState; switch(currState) { case WAITING_IDLE: // If we get a new RFID message if(RFID_Ready) { // Clear flag for next time throughwe RFID_Ready = 0; // Select RFID PIC as slave SS_RFID = 0; // Send a dummy byte to enable transfer SSPBUF = DUMMY_BYTE; counter++; nextState = WAITING_FOR_RFID; } break; case WAITING_FOR_RFID: // Once we get a response from RFID PIC if(BF) { // If it's not our last byte if(counter < RFID_MESSAGE_LENGTH) { // Get byte, clears BF RFID_Message[counter-1] = SSPBUF; // Send a dummy byte to enable transfer SSPBUF = DUMMY_BYTE; counter++; } // If we got our last byte else { // Get byte, clears BF RFID_Message[counter-1] = SSPBUF; // Done counter = 0; // De-select RFID PIC as slave SS_RFID = 1; // If checksum passes, return 0, // VerifyCheckSum also converts the ASCII data to HEX if(VerifyChecksum() == 0) { // Prepare message to Security Controller MakeSecurityMessage(); // Wait for xmit register to empty, technically blocking code, // but TXIF should never be 0 here while(!TXIF); // Send out the first byte TXREG = Security_TX[0]; counter++; nextState = SENDING_TO_SECURITY_PIC; } else nextState = WAITING_IDLE; } BF = 0; // probably not needed SSPIF = 0; // Clear so that Main PIC message sends } break; case SENDING_TO_SECURITY_PIC: // If Xmit register empty if(TXIF) { // Send out message if(counter < SK_SEND_LENGTH) { TXREG = Security_TX[counter]; counter++; } // Done sending out message else { counter = 0; nextState = RECEIVING_FROM_SECURITY_PIC; } } break; case RECEIVING_FROM_SECURITY_PIC: // If we got another byte from Security Controller if(RCIF) { // Get the bytes, clears RCIF Security_RX[counter] = RCREG; // Not done yet if(counter < (SK_RECEIVE_LENGTH - 1)) counter++; // Get the last (6th) byte else if (counter == SK_RECEIVE_LENGTH-1) { counter = 0; // Select SS of Main PIC SS_MAIN = 0; // Prepare message to Main PIC MakeMainMessage(); SSPBUF = Main_Message[0]; counter++; nextState = SENDING_TO_MAIN_PIC; } } break; case SENDING_TO_MAIN_PIC: // If finished last transmission if(SSPIF && BF) { // Read SSPBUF garbage to clear BF SSPBUF; // Manually clear flag SSPIF = 0; // Send the rest of the message if(counter < MAIN_SEND_LENGTH) { SSPBUF = Main_Message[counter]; counter++; } else { counter = 0; // Deselect SS of Main PIC SS_MAIN = 1; nextState = WAITING_IDLE; } // Done } break; } currState = nextState; } unsigned char ConvertASCIItoHEX(unsigned char upper, unsigned char lower) { static unsigned char hex, lower_hex; // Upper nibble: if < 0x40, AND w/ 0x0F, otherwise subtract 0x37, then bit shift hex = (upper < 0x40)?(upper & 0x0F):(upper - 0x37); hex = hex<<4; // Lower nibble: same as above, without bit shift, add to upper to get full HEX lower_hex = (lower < 0x40)?(lower & 0x0F):(lower - 0x37); hex += lower_hex; return hex; } unsigned char VerifyChecksum(void) { static unsigned char i, checksum; // Convert received ASCII characters to HEX for(i=0; i<RFID_HEX_LENGTH; i++) RFID_Hex[i] = ConvertASCIItoHEX(RFID_Message[2*i+1], RFID_Message[2*i+2]); // Calculate the checksum: // XOR all the converted HEX values after the start of data ASCII charactr (0x02) checksum = RFID_Hex[0]; for(i=1; i<RFID_HEX_LENGTH; i++) checksum ^= RFID_Hex[i]; // Should return 0 if we had a valid checksum since our last operation was XOR w/ checksum return checksum; } void MakeSecurityMessage(void) { static unsigned char i; Security_TX[0] = 0x04; for (i=1; i<4; i++) Security_TX[i]= RFID_Hex[i+1]; Security_TX[4] = 0x08; } void MakeMainMessage(void) { // S1-S3 Main_Message[0] = Security_TX[1]; Main_Message[1] = Security_TX[2]; Main_Message[2] = Security_TX[3]; // SK1-SK3 Main_Message[3] = Security_RX[0]; Main_Message[4] = Security_RX[2]; Main_Message[5] = Security_RX[4]; } #ifdef SECURITY_TEST void main(void) { Init(); TimerPIC_Init(); GIE = 1; TRISA1 = 0; // test output //TimerPIC_InitTimer(7,200); RA1 = 1; while(1) { Update(); /* if(TimerPIC_IsTimerExpired(7) == TimerPIC_EXPIRED){ TimerPIC_ClearTimerExpired(7); TimerPIC_InitTimer(7,200); RA1 ^= 1; } */ } } #endif