; RFID PIC Module
; This module:
; (1) Receives RFID bytes from RDM630 RFID card reader over UART
; (2) Sends the exact message over to the Security PIC over SPI
;

;      PORT DIAGRAM AND PINOUT FOR RFID PIC
;*************************************************
; 1  +5V         VDD            VSS   GND        20
; 2  OSC1        PORT A5    PORT A0   RFID_READY 19
; 3  OSC2        PORT A4    PORT A1   	         18
; 4              PORT A3    PORT A2              17
; 5              PORT C5    PORT C0              16
; 6              PORT C4    PORT C1              15
; 7              PORT C3    PORT C2              14
; 8  SPI-SS      PORT C6    PORT B4   SPI-SDI    13
; 9  SPI-SDO     PORT C7    PORT B5   RX         12
; 10             PORT B7    PORT B6   SPI-SCK    11
;*************************************************

        list    P=PIC16F690
#include "p16F690.inc"
        __config (_MCLRE_OFF & _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC)

		errorlevel -302	; Get rid of Bank0 warning
;
; variable definitions, don't need banksel in common address space
;
W_Temp			equ		0x70			; Save W during interrupts
Status_Temp		equ		0x71			; Save Status during interrupts
ByteCounter		equ		0x72
Flags			equ		0x74

; Flags
Last_SPI		equ		0				; Set when about to send last SPI

; I/O
RFID_READY		equ		0				; Transmit RFID data over the SPI line

;
; bit definitions
;
SetBaudRate		equ		0x81			; Ox81=129 => 20e6/(16(129+1)) = 9600
LastRFIDByte	equ		0x0E			; 14th byte received

OutputPortsA	equ		b'11111000'		; Ports A0-A2 will be outputs

;
;Tables
;
RFID0       equ      	0x20
RFID1       equ     	0x21
RFID2       equ      	0x22
RFID3       equ    		0x23
RFID4       equ        	0x24
RFID5       equ        	0x25
RFID6       equ        	0x26
RFID7       equ        	0x27
RFID8       equ        	0x28
RFID9       equ        	0x29
RFID10      equ        	0x2A
RFID11      equ        	0x2B
RFID12      equ        	0x2C
RFID13      equ        	0x2D


		org 0
			GOTO 		Main
		org 4
         	GOTO		IntResponse
		org 5
EndTbl
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Main:

; Run Initialization Routine
Initialize:
			BANKSEL		ANSEL			; Set all analog bits to digital
			CLRF		ANSEL
			CLRF		ANSELH

			BANKSEL 	TRISA			; Set output ports
			;MOVLW		OutputPortsA
			;ANDWF		TRISA,f
			BCF			TRISA,RFID_READY

			; Regular I/O
			BANKSEL		PORTA		    ; Initialize port values
    	    CLRF   		PORTA 	        ; Clear all outputs, including RFID_RDY

			; SCI (probably not needed)
			BANKSEL		TRISB
			BSF			TRISB,4			; SDI: Input
			BSF			TRISB,6			; SCK: Input (from Master)
			BANKSEL		TRISC
			BSF			TRISC,6			; SS: Input
			BCF			TRISC,7			; SDO: Output

			; EUSART (probably not needed)
			BANKSEL		TRISB
			BSF			TRISB,5			; RX: Input
			BCF			TRISB,7			; TX: Output

; Configure EUSART
InitEusart:
			BANKSEL		TXSTA
			BCF			TXSTA,SYNC		; Enable asynchronous serial transmission port
			BSF			TXSTA,TXEN		; Enable transmissions
			BCF			TXSTA,TX9		; 8-bit transmit
			BSF			TXSTA, BRGH
			BANKSEL		RCSTA
			BSF			RCSTA,SPEN		; Enable asynchronous serial reception port
			BSF			RCSTA,CREN		; Enable receptions
			BCF			RCSTA,RX9		; 8-bit receive

			BANKSEL		SPBRG			; Set baud rate to 9600
			MOVLW		SetBaudRate
			MOVWF		SPBRG
			CLRF		SPBRGH

; Configure SPI
InitSPI:
			BANKSEL		SSPCON
			MOVLW		b'00110100'
			MOVWF		SSPCON			; 0xxxxxxx = No write collision detect
										; x0xxxxxx = No receive overflow indicator
										; xx1xxxxx = Enable serial port, SCK, SDO, SDI as serial pins
										; xxx1xxxx = Clock idles high
										; xxxx0100 = SPI Slave, clock = SCK, SS pin control enabled
			BANKSEL		SSPSTAT
			MOVLW		b'00000000'
			MOVWF		SSPSTAT			; 0xxxxxxx = Data sampled in middle of output
										; x0xxxxxx = Data transmitted on falling edge of SCK
										; xxXXXXXX = Read only

			BCF			Flags,Last_SPI	; Not waiting to send our last SPI message

; Configure Interrupts
InitInterrupts:
			BANKSEL		PIE1
			BSF			PIE1,RCIE		; EUSART from RFID
			BSF			PIE1,SSPIE		; SPI from Security PIC
			BANKSEL		INTCON
			BSF			INTCON,PEIE		; Peripheral
			BSF			INTCON,GIE		; Global

; Initialize Variables
InitVariables:

			CLRF		ByteCounter		; Byte counter is 0

; Start endless loop while you wait for interrupts
Loop:
   			GOTO		Loop



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Functions;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Determine what interrupt was triggered and route to handling function
IntResponse:

			MOVWF   	W_Temp          ; Save W while in interrupt, accessible from any bank
    		SWAPF   	STATUS,W        ; Swap STATUS nibbles and send to W
    		MOVWF   	Status_Temp		; Save STATUS while in interrupt, accessible from any bank

			BANKSEL		PIR1
			BTFSC		PIR1,SSPIF		; Check if we had an SPI message
			GOTO		SPIResponse
			BTFSC		PIR1,RCIF		; Check if we had a EUSART message
			GOTO		EusartResponse
			GOTO		IntDone			; Error if this happens

; SPI Response: send out RFID message
SPIResponse:
			BANKSEL		SSPBUF
			MOVF		SSPBUF,W		; Probably not needed

			BANKSEL		PIR1
			BCF			PIR1,SSPIF		; Clear SSPIF in software

			BTFSC		Flags,Last_SPI	;
			GOTO		LastSPI			; Last time, so we shouldn't load in more values
			GOTO		NormalSPI		; Middle time, just load in one value

; Regular RFID send, so send byte while loading in next byte
NormalSPI:
			MOVLW		0x20			; Start of RFID Table
			ADDWF		ByteCounter,W	; Increment RFID Table by number of bytes we are at
			MOVWF		FSR				; W = 0x20 + ByteCounter
			MOVF		INDF,W			; Load in the byte
			MOVWF		SSPBUF			; Send it out next time through

			INCF		ByteCounter,F	; Increment byte
			MOVLW		LastRFIDByte
			XORWF		ByteCounter,W	; Check if you sent out the last byte
			BTFSC 		STATUS,Z
			BSF			Flags,Last_SPI	; If loaded in last RFID byte, set flag

			GOTO		IntDone

; Last RFID send, so get ready for RFID receive, don't load SSPBUF
LastSPI:
			CLRF		ByteCounter		; If it is, done with message, so reset the ByteCounter

			BCF			Flags,Last_SPI	; Done with last RFID send

			BANKSEL		PORTA
			BCF			PORTA,RFID_READY; Get ready for next RFID message send

			GOTO		IntDone

; A EUSART message from the RFID was received
EusartResponse:
			MOVLW		0x20			; Start of RFID Table
			ADDWF		ByteCounter,W	; Increment RFID Table by number of bytes we are at

			MOVWF		FSR				; W = 0x20 + ByteCounter, load pointer
			BANKSEL		RCREG
			MOVF		RCREG,W			; Take the Recieved Byte and move it to the RFID Table
			MOVWF		INDF			; Should clear RCIF


			INCF		ByteCounter,F	; Increment Byte Recieved
			MOVLW		LastRFIDByte
			XORWF		ByteCounter,W	; Check if you got the last byte
			BTFSC 		STATUS,Z
			CALL		Last_EUSART		;

			GOTO		IntDone

; Got our last EUSART message
Last_EUSART:
			CLRF		ByteCounter		; If it is, done with message, so reset the ByteCounter

			BANKSEL		SSPBUF
			MOVF		SSPBUF,W		; Probably not needed
			BANKSEL		PIR1
			BCF			PIR1,SSPIF		; Clear SSPIF in software

			; Preload the buffer so we can auto-send data when we get an SPI interrupt
			MOVLW		0x20			; Start of RFID Table
			ADDWF		ByteCounter,W	; Increment RFID Table by number of bytes we are at
			MOVWF		FSR				; W = 0x20 + ByteCounter
			MOVF		INDF,W			; Load in the byte

			INCF		ByteCounter,F	; Increment Byte Received

			BANKSEL		PORTA
			BSF			PORTA,RFID_READY; Tell Master PIC we are read to send RFID message

			RETURN

; Exit interrupt response
IntDone:
			SWAPF		Status_Temp,W	; Swap nibbles in Status_Temp again and move to W
			MOVWF		STATUS			; Restore status
			SWAPF		W_Temp,F		; Swap nibbles in W_Temp and overwrite the file
			SWAPF		W_Temp,W		; Swap nibbles in W_Temp and save in W
			RETFIE						; Return and re-enable interrupts
			END