LIST P=P16F876A INCLUDE P16F876A.INC ;====================================== __CONFIG _BODEN_ON & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _XT_OSC TIMER1 EQU H'20' ; Used in delay routine TIMER2 EQU H'21' ; " " " TIMER3 EQU H'22' ; " " " COUNT1 EQU H'25' ; used in delay routine COUNTa EQU H'26' ; used in delay routine COUNTb EQU H'27' ; used in delay routine ReceivedByte EQU H'28' ; used as a temporary memory for data received from card COUNTBIT EQU H'29' ; used in the ReceiveByte_ATR routine BITNUMBER EQU H'2a' ; used in the ReceiveByte_ATR routine ParityCheckVar EQU H'2b' ; used in the ReceiveByte_ATR routine HistCount EQU H'2c' ; used in historicalbyte routines TS EQU H'40' ; initial character T0 EQU H'41' ; format character TA1 EQU H'42' ; interface character TB1 EQU H'43' ; interface character TC1 EQU H'44' ; interface character TD1 EQU H'45' ; interface character TA2 EQU H'46' ; interface character TB2 EQU H'47' ; interface character TC2 EQU H'48' ; interface character TD2 EQU H'49' ; interface character TA3 EQU H'4a' ; interface character TB3 EQU H'4b' ; interface character TC3 EQU H'4c' ; interface character TD3 EQU H'4d' ; interface character SendByte EQU H'50' ; used in SendCharacter ByteCounter EQU H'51' ; used in the readfile routine ByteCounter2 EQU H'52' ; used in the readfile routine ByteCounter3 EQU H'53' ; used in the readfile routine WREG_TEMP EQU H'60' ; storage for WREG during interrupt STATUS_TEMP EQU H'61' ; storage for STATUS during interrupt PCLATH_TEMP EQU H'62' ; storage for PCLATH during interrupt FSR_TEMP EQU H'63' ; storage for FSR during interrupt DATAIN1 EQU H'70' ; received data from PC -> Zero for BlockComplete DATAIN2 EQU H'71' ; received data from PC -> 16 \ DATAIN3 EQU H'72' ; received data from PC -> 15 | DATAIN4 EQU H'73' ; received data from PC -> 14 | DATAIN5 EQU H'74' ; received data from PC -> 13 | DATAIN6 EQU H'75' ; received data from PC -> 12 | DATAIN7 EQU H'76' ; received data from PC -> 11 | DATAIN8 EQU H'77' ; received data from PC -> 10 | DATAIN9 EQU H'78' ; received data from PC -> 9 } Name Characters for LCD DATAIN10 EQU H'79' ; received data from PC -> 8 | DATAIN11 EQU H'7a' ; received data from PC -> 7 | DATAIN12 EQU H'7b' ; received data from PC -> 6 | DATAIN13 EQU H'7c' ; received data from PC -> 5 | DATAIN14 EQU H'7d' ; received data from PC -> 4 | DATAIN15 EQU H'7e' ; received data from PC -> 3 | DATAIN16 EQU H'7f' ; received data from PC -> 2 | DATAIN17 EQU H'6f' ; received data from PC -> 1 / DATAIN18 EQU H'6e' ; received data from PC -> Access Granted: 0xff OR Access Denied: 0xFE ; Define ports LCDControl EQU PORTC ; LCD control lines (C4-C5) Card EQU PORTA ; data from card ; To work with the display RegSel EQU H'0004' ; Register Select Signal (C4) Enable EQU H'0005' ; Enable signal LCD (C5) ; To work with the ICC Inserted EQU H'0000' ; Check whether the card is inserted (A0) Reset EQU H'0001' ; Reset signal to card (A1) IO EQU H'0002' ; Input/Output line for ICC (A2) OpenDoor EQU H'0003' ; Output signal to open the door ;---------------------------------------------------------------------------- ;RESET Interrupt Vector ORG 0x0000 ; reset vector GOTO Main nop nop ;---------------------------------------------------------------------------- ;OTHER Interrupt Vector ORG 0x0004 ; interrupt vector GOTO Int ;---------------------------------------------------------------------------- Main BSF STATUS, RP0 ; select file register bank 1 MOVLW 0x00 ; 0000 0000 MOVWF TRISB ; B0-B7: output MOVLW B'00000101' ; 0000 0101 MOVWF TRISA ; A0 input, A1 output, A2 = I/O line, A3 output MOVLW b'00000000' ; 0000 0000 MOVWF TRISC ; all output BSF ADCON1, 0x01 ; only digital BSF ADCON1, 0x02 BCF ADCON1, 0x03 BCF STATUS, RP0 ; select file register bank 0 MOVLW 0x00 ; 0000 0000 MOVWF PORTA ; RA ports clear MOVWF PORTB ; RB ports clear MOVWF PORTC ; RC ports clear CALL SetupSerial CALL DELAY_1000 ; wait for LCD to settle CALL LCD_Init ; setup LCD CALL LCD_Init CALL Screen_Welcome NewCardSession CALL Screen_InsertCard CALL ClearVariables CALL Card_Init CALL WaitForCard ; Allow time for the connections to be made ; Lower this time later if desired CALL Screen_InProgress CALL DELAY255 CALL CheckIO CALL ResetCard CALL AnswerToReset CALL GetCardNumber CALL Card_Deactivate GOTO WaitForAccess Showw ; put W as output on port B and abort execution, used for testing purposes only MOVWF PORTB BSF Card,OpenDoor goto WaitForCardRemoval WaitForCardRemoval BTFSS Card,Inserted GOTO NewCardSession GOTO WaitForCardRemoval ;------------------------------- ;****************************************************************************** ; CARD routines ;****************************************************************************** ; Card main routines ;------------------- Card_Init BCF Card,OpenDoor ; Make sure the door is closed before beginning BCF Card,Reset ; Reset line to Low BSF STATUS, RP0 ; select file register bank 1 BSF TRISA,IO ; set IO to input BCF STATUS, RP0 ; select file register bank 0 RETURN WaitForCard BTFSS Card,Inserted GOTO WaitForCard ; Card not inserted RETURN ; Card inserted, continue CheckIO BTFSS Card,IO GOTO Reject_Wrongside ; Card IO L -> Card inserted wrong side RETURN ; Card IO H -> Card inserted ok, continue ResetCard CALL DELAY10 ; wait 40000 card clock cycles --> 20ms for PIC ###nu 2MHZ klok dus 20 ipv 10 BSF Card,Reset ; send reset signal to card RETURN AnswerToReset ; executed after RESET request by Terminal ReceiveATR ; IO L, ATR will follow ;CALL CountETU ;CALL LCD_Char ;CALL WaitForCardRemoval CALL ReceiveByte_ATR ; Receive TS, should be 3B = 0011 1011 MOVWF TS ; Store TS XORLW 0x3b ; check if W equal to 3B BTFSS STATUS, Z ; Z=1 when equal GOTO Reject_Card CALL ReceiveByte_ATR ; Receive T0 MOVWF T0 ; Store T0 CALL ReceiveByte_ATR ; Receive TB1 MOVWF TB1 ; Store TB1 CALL ReceiveByte_ATR ; Receive TC1 MOVWF TC1 ; Store TC1 CALL ReceiveHistoricalBytes ; Receive historical bytes, indicated by the ls 4 bits of T0 RETURN GetCardNumber CALL SendCommand_SelectRoot ; browse to the Purse File on the smartcard CALL SendCommand_SelectFile ; " " " " " " ; We want to read byte 105 to 112 in the response sequence (8 bytes for bank card number) MOVLW d'112' MOVWF ByteCounter2 ; contains the number of the last byte in the sequence you want to read MOVLW d'8' MOVWF ByteCounter3 ; contains the amount of bytes you want to read INCF ByteCounter3 CALL SendCommand_ReadFile ; Read the Purse File (which contains smartcard number) RETURN Card_Deactivate BCF Card,Reset RETURN WaitForAccess GOTO WaitForCardRemoval ; Do nothing while waiting for PC to send Access Data ProcessAccessData ; Called from within the interrupt on receiving data from PC ; DATAIN17-DATAIN2 contains the Name of the person (first letter in 17) ; DATAIN18 contains: 0xff if the person is allowed inside ; 0x00 if the person is not allowed inside BTFSS DATAIN18,0 GOTO AccessDenied GOTO AccessGranted AccessGranted ; write "Welcome name" on screen CALL Screen_AccessGranted CALL Screen_WriteName CALL Open_Door CALL Screen_RemoveCard RETURN Returns to the interrupt to finish it and then resumes the WaitForCardRemoval Loop, NewCardSession happens automatically on card removal AccessDenied ; write "Access Denied" on screen CALL Screen_AccessDenied RETURN ; Returns to the interrupt to finish it and then resumes the WaitForCardRemoval Loop, NewCardSession happens automatically on card removal Open_Door BSF Card,OpenDoor Call DELAY_1000 Call DELAY_1000 Call DELAY_1000 Call DELAY_1000 Call DELAY_1000 Call DELAY_1000 Call DELAY_1000 BCF Card,OpenDoor Call DELAY_1000 Call DELAY_1000 Call DELAY_1000 RETURN CountETU ; used for measuring etu's (test purpose only) MOVLW 0x00 MOVWF TIMER3 ; reeds 6 instructies gepasseerd CountETU_begin BTFSC Card,IO GOTO CountETU_begin ; wait for START BIT CountETU_loop ; elke loop 4 instructies ; 6+4xtimer = totaal aantal instructies = 22 LOW (timer = 4) 9 INCF TIMER3 BTFSS Card,IO GOTO CountETU_loop CountETU_loop2 ; 2+4xtimer = 38 HI (timer = 9) 14 INCF TIMER3 BTFSC Card,IO GOTO CountETU_loop2 CountETU_loop3 ; 2+4xtimer = 22 LO (timer = 4) 5 INCF TIMER3 BTFSS Card,IO GOTO CountETU_loop3 CountETU_loop4 ; 2+4xtimer = 58 HI (timer = 14) 9 INCF TIMER3 BTFSC Card,IO GOTO CountETU_loop4 CountETU_loop5 ; 2+4xtimer = 38 LO (timer = 9) 4 INCF TIMER3 BTFSS Card,IO GOTO CountETU_loop5 ;CountETU_loop6 ; 2+4xtimer = 154 HI (timer = 38) 14 ; INCF TIMER3 ; BTFSC Card,IO ; GOTO CountETU_loop6 ;CountETU_loop7 ; 2+4xtimer = 154 LO (timer = 38) 43 ; ;INCF TIMER3 ; BTFSS Card,IO ; GOTO CountETU_loop7 ;CountETU_loop8 ; 2+4xtimer = 154 HI (timer = 38) 33 ; INCF TIMER3 ; BTFSC Card,IO ; GOTO CountETU_loop8 MOVF TIMER3,0 ; zet timer3 in W ;MOVWF PORTB ;GOTO MAINLOOP RETURN ; ; Conclusies over CountETU FORTIS KAART ; - 1 ETU = ongeveer 19 instructies = 38 micros ; - sequentie ontvangen: LHHLHHHLLH (komt overeen met TS = '3B', zoals verwacht) ; - tussen opeenvolgende bytes is er een guardtime van 154 instructies = 308 micros ; Let er dus voor op dat de controle (parity) en verwerking van een byte niet meer dan 154 instructies mag bedragen!!! ; Card Common routines ;--------------------- ReceiveByte_ATR ; This subroutine should be called while the IO line is High and waiting for a byte to come ; Performs parity check and returns the received byte in W ; Caution: use during ATR only MOVLW 0x00 MOVWF ParityCheckVar CALL MakeIO_Input WaitForByte BTFSC Card,IO ; Check IO GOTO WaitForByte ; Wait for IO to go LOW (start bit) MOVLW D'14' ; 1.5 ETU CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,0 ; IO port L BTFSC Card,IO BSF ReceivedByte,0 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,1 ; IO port L BTFSC Card,IO BSF ReceivedByte,1 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,2 ; IO port L BTFSC Card,IO BSF ReceivedByte,2 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,3 ; IO port L BTFSC Card,IO BSF ReceivedByte,3 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,4 ; IO port L BTFSC Card,IO BSF ReceivedByte,4 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,5 ; IO port L BTFSC Card,IO BSF ReceivedByte,5 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,6 ; IO port L BTFSC Card,IO BSF ReceivedByte,6 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ReceivedByte,7 ; IO port L BTFSC Card,IO BSF ReceivedByte,7 ; IO port H MOVLW D'8' CALL DELAY_MICROS BTFSS Card,IO BCF ParityCheckVar,0 ; IO port L BTFSC Card,IO BSF ParityCheckVar,0 ; IO port H ;;; ;;; Perform Parity Check ;;; This must take longer than 6 instructions in order to complete the last ;;; transmitted bit (etu) to avoid conflicts with subsequent bytes ;;; BTFSC ReceivedByte,0 INCF ParityCheckVar BTFSC ReceivedByte,1 INCF ParityCheckVar BTFSC ReceivedByte,2 INCF ParityCheckVar BTFSC ReceivedByte,3 INCF ParityCheckVar BTFSC ReceivedByte,4 INCF ParityCheckVar BTFSC ReceivedByte,5 INCF ParityCheckVar BTFSC ReceivedByte,6 INCF ParityCheckVar BTFSC ReceivedByte,7 INCF ParityCheckVar BTFSC ParityCheckVar,0 ; check the l.s. bit GOTO ParityError ; parity error MOVF ReceivedByte,0 ; Put ReceivedByte in W RETURN ; Return with ReceivedByte in W ReceiveHistoricalBytes MOVLW 0x00 MOVWF HistCount BTFSC T0,0 BSF HistCount,0 BTFSC T0,1 BSF HistCount,1 BTFSC T0,2 BSF HistCount,2 BTFSC T0,3 BSF HistCount,3 INCF HistCount ; amount of historical bytes given by T0 determined ReceiveHistoricalBytesLoop DECFSZ HistCount GOTO ReceiveHistoricalByte RETURN ReceiveHistoricalByte CALL ReceiveByte_ATR GOTO ReceiveHistoricalBytesLoop ;ReceiveByte_ATR ; MOVLW 0x07 ; MOVWF COUNTBIT ; CLRF ParityCheckVar ; MOVLW d'165' ; Set delay time ; CALL DELAY_MICROS ; delay 1,5 etu ; ReceiveBit ; MOVLW 0x01 ; ADDWF COUNTBIT,0 ; Add COUNTBIT to W ; MOVWF BITNUMBER ; Create BITNUMBER ; ; BTFSS Card,IO ; read IO port ; BCF ReceivedByte,BITNUMBER ; IO port L ; BTFSC Card,IO ; BSF ReceivedByte,BITNUMBER ; IO port H ; ; BTFSC ReceivedByte,BITNUMBER ; INCF ParityCheckVar ; Increment ParityCheckVar by 1 ; DECFSZ COUNTBIT ; GOTO ReceiveBit_WaitEtu ; Receive next bit ; BTFSC Card,IO ; read IO port for Parity bit ; INCF ParityCheckVar ; Increment ParityCheckVar by 1 ; BTFSC ParityCheckVar,0x01 ; ParityCheck, test l.s. bit (determines odd/even) ; GOTO NewCardSession ; parity check odd, retry card ;;;;;; warmreset? reject card? ; RETLW ReceivedByte ; parity check even, continue (return with ReceivedByte in W) ; ;ReceiveBit_WaitEtu ; MOVLW d'100' ; set delay time ; CALL DELAY_MICROS ; delay 1 etu ; GOTO ReceiveBit ; resume receivebyte loop ; Card command routines ;------------------------ SendCommand_ReadRecord ; Read Record Command ; CLA = 00 -> parity 0 MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0x04 ; 0000 0100 CALL SendCharacter ; INS = B2 -> parity 0 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0xb2 ; 1011 0010 CALL SendCharacter ; P1 = 01? -> parity 1 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x03 CALL SendCharacter ; P2 = 0C? -> parity 0 MOVLW 0x00 MOVWF ParityCheckVar MOVLW b'00010100' CALL SendCharacter ; Lc = 00 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 ; 1111 1111 CALL SendCharacter MOVLW d'3' CALL DELAY_MICROS ; wait 1 etu to let the parity signal pass CALL ReceiveByte_ATR ; Receive Procedure Byte (should be equal to INS) CALL Showw ;CALL ReceiveByte_ATR ; 90 ;CALL ReceiveByte_ATR ; 00 9000: Command Successful RETURN SendCommand_ReadFile ; bc b0 00 00 ff (The last byte determines how much bytes of the file are returned (ff = 255) ; Read Record Command ; CLA = 00 -> parity 0 MOVLW 0x01 ; 0x01 MOVWF ParityCheckVar MOVLW 0xbc ; 1011 1100 ; 0xbc CALL SendCharacter ; INS = B2 -> parity 0 MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0xb0 ; 1011 0000 CALL SendCharacter ; P1 = 01? -> parity 1 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter ; P2 = 0C? -> parity 0 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter ; Lc = 00 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0xff CALL SendCharacter MOVLW d'3' CALL DELAY_MICROS ; wait 1 etu to let the parity signal pass CALL ReceiveByte_ATR ; Receive Procedure Byte (should be equal to INS) ; FILE: 17FF 2901 ;CALL ReceiveByte_ATR ; 1: 00 05 ;CALL ReceiveByte_ATR ; 2: 00 60 ;CALL ReceiveByte_ATR ; 3: 00 01 ;CALL ReceiveByte_ATR ; 4: 00 00 ;CALL ReceiveByte_ATR ; 5: 00 82 ;CALL ReceiveByte_ATR ; 6: 00 D4 ;CALL ReceiveByte_ATR ; 7: 00 F5 ;CALL ReceiveByte_ATR ; 8: 00 50 ;CALL ReceiveByte_ATR ; 9: 09 ;CALL ReceiveByte_ATR ; 10: 78 MOVFW ByteCounter2 MOVWF ByteCounter ; Move the byte number we want to read to ByteCounter DECFSZ ByteCounter3 ; Decrease amount of bytes left to be read GOTO $+2 ; If there are bytesleft, skip the next line GOTO StopReading ; If no bytes left, stop reading the card ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; This piece of code allows you to select a byte in the response sequence ;;;; ;;;; The number of the byte you wish to read should be in ByteCounter at start. ;;;; SkipByte CALL ReceiveByte_ATR ; received byte is stored in W DECFSZ ByteCounter GOTO SkipByte CALL SendSerial ; send byte in W (Progress Bar) MOVLW A'_' CALL LCD_Char MOVLW A'_' CALL LCD_Char CALL DELAY255 ; Give time for the read command to finish DECFSZ ByteCounter2 goto SendCommand_ReadFile ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; StopReading ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; This piece of code allows you to select a byte in the response sequence ;;;; ;;;; The number of the byte you wish to read should be in ByteCounter at start. ;;;; ; MOVLW d'255' ; MOVWF ByteCounter ; NextByte ; CALL ReceiveByte_ATR ; CALL SendSerial ; DECFSZ ByteCounter ; GOTO NextByte ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;CALL ReceiveByte_ATR ; 90 ;CALL ReceiveByte_ATR ; 00 9000: Command Successful RETURN SendCommand_SelectFile ; bc a4 00 00 02 ; 29 01 ; The last 2 bytes are the ID of the file ; Purse File = 2901 ; ICC ID file = 17FF ; Read Record Command ; CLA MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0xbc ; 1011 1100 CALL SendCharacter ; INS MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0xa4 ; 1010 0100 CALL SendCharacter ; P1 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter ; P2 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter ; Lc MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0x02 CALL SendCharacter MOVLW d'3' CALL DELAY_MICROS ; wait 1 etu to let the parity signal pass CALL ReceiveByte_ATR ; Receive Procedure Byte (should be INS) ; Send Data Bytes MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0x29 ; 0010 1001 CALL SendCharacter MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0x01 CALL SendCharacter MOVLW d'3' CALL DELAY_MICROS ; wait 1 etu to let the parity signal pass ; Receive Response CALL ReceiveByte_ATR ; Receive Status bytes (Should be 90 00) CALL ReceiveByte_ATR RETURN SendCommand_SelectRoot ; Select the Root file on the ICC ; bc a4 00 00 02 ; 3f 00 ; CLA MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0xbc ; 1011 1100 CALL SendCharacter ; INS MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0xa4 ; 1010 0100 CALL SendCharacter ; P1 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter ; P2 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter ; Lc MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0x02 CALL SendCharacter MOVLW d'3' CALL DELAY_MICROS ; wait 1 etu to let the parity signal pass CALL ReceiveByte_ATR ; Receive Procedure Byte (should be INS) ; Send Data MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x3f ; 0011 1111 CALL SendCharacter MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter MOVLW d'3' CALL DELAY_MICROS ; wait 1 etu to let the parity signal pass ; Receive Response CALL ReceiveByte_ATR ; Receive Status bytes (Should be 90 00) CALL ReceiveByte_ATR RETURN SendCommand ; Read Record Command ; CLA = 00 -> parity 0 MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0xbc ; 1011 1100 CALL SendCharacter ; INS = B2 -> parity 0 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0xB2 CALL SendCharacter ; P1 = 01? -> parity 1 MOVLW 0x01 MOVWF ParityCheckVar MOVLW 0x01 CALL SendCharacter ; P2 = 0C? -> parity 0 MOVLW 0x00 MOVWF ParityCheckVar MOVLW b'00001100' CALL SendCharacter ; Lc = / not present ; Data= / not present ; Le = 00 MOVLW 0x00 MOVWF ParityCheckVar MOVLW 0x00 CALL SendCharacter MOVLW d'3' CALL DELAY_MICROS ; wait 1 etu to let the parity signal pass RETURN SendCharacter MOVWF SendByte MOVLW d'220' ; minimal 16 ETU waittime before sending char (max 9600 etu) CALL DELAY_MICROS CALL MakeIO_Output ; determine parity checkvariable, if odd, the l.s. bit of ParityCheckVar will be 1 ;MOVLW 0x00 ;MOVWF ParityCheckVar ;BTFSC SendByte,0 ;INCF ParityCheckVar ;BTFSC SendByte,1 ;INCF ParityCheckVar ;BTFSC SendByte,2 ;INCF ParityCheckVar ;BTFSC SendByte,3 ;INCF ParityCheckVar ;BTFSC SendByte,4 ;INCF ParityCheckVar ;BTFSC SendByte,5 ;INCF ParityCheckVar ;BTFSC SendByte,6 ;INCF ParityCheckVar ;BTFSC SendByte,7 ;INCF ParityCheckVar ; SendByte (Hi or Lo) contains the byte that is being transmitted ; Direct convention -> l.s. bit gets sent first BCF Card,IO ; Send the START BIT MOVLW D'9' ; CALL DELAY_MICROS ; Wait 1 ETU BTFSS SendByte,0 BCF Card,IO BTFSC SendByte,0 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS SendByte,1 BCF Card,IO BTFSC SendByte,1 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS SendByte,2 BCF Card,IO BTFSC SendByte,2 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS SendByte,3 BCF Card,IO BTFSC SendByte,3 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS SendByte,4 BCF Card,IO BTFSC SendByte,4 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS SendByte,5 BCF Card,IO BTFSC SendByte,5 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS SendByte,6 BCF Card,IO BTFSC SendByte,6 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS SendByte,7 BCF Card,IO BTFSC SendByte,7 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS BTFSS ParityCheckVar,0 BCF Card,IO BTFSC ParityCheckVar,0 BSF Card,IO MOVLW D'8' ; Wait 1 ETU CALL DELAY_MICROS ; Character sent, wait 1 ETU for parity response from ICC CALL MakeIO_Input ; 7 instructions movlw d'8' ; 1 instruction call DELAY_MICROS ; 28 instructions BTFSS Card,IO GOTO ParityError ; Parity error! Abort (implement resending character later) RETURN ; Character sent successfully! SendCLA ; Subroutine used to test sending of the command 0x00 to the ICC MOVLW d'110' ; minimal 16 ETU waittime before sending char (max 9600 etu) CALL DELAY_MICROS CALL MakeIO_Output ; cla = 00 BCF Card,IO ; start bit movlw d'4' ; 5 call DELAY_MICROS ; Wait 1 etu = 17.62 instructions BSF Card,IO ; 1 movlw d'4' call DELAY_MICROS BCF Card,IO ; 2 movlw d'4' call DELAY_MICROS BCF Card,IO ; 3 movlw d'4' call DELAY_MICROS BCF Card,IO ; 4 movlw d'4' call DELAY_MICROS BCF Card,IO ; 5 movlw d'4' call DELAY_MICROS BCF Card,IO ; 6 movlw d'4' call DELAY_MICROS BCF Card,IO ; 7 movlw d'4' call DELAY_MICROS BCF Card,IO ; 8 movlw d'4' call DELAY_MICROS BSF Card,IO ; parity bit movlw d'4' call DELAY_MICROS ; Wait 1 etu ; Character sent, wait 1 ETU for parity response from ICC CALL MakeIO_Input ; 7 instructions movlw d'2' ; 1 instruction call DELAY_MICROS ; 10 instructions BTFSS Card,IO GOTO ParityError ; Parity error! Abort (implement resending character later) RETURN ; Character sent successfully MakeIO_Input ; 7 instructions including call and return BSF STATUS, RP0 ; select file register bank 1 BSF TRISA,IO ; input BCF STATUS, RP0 ; select file register bank 0 RETURN MakeIO_Output ; 7 instructions including call and return BSF STATUS, RP0 ; select file register bank 1 BCF TRISA,IO ; output BCF STATUS, RP0 ; select file register bank 0 RETURN ; Card rejection routines ;------------------------ Reject_Wrongside CALL Screen_WrongSide GOTO WaitForCardRemoval ; wait for card removal Reject_Card CALL Card_Deactivate CALL Screen_CardRejected GOTO WaitForCardRemoval ; Wait for card removal ParityError GOTO Reject_Card ; Improved error handling can be implemented in the future ;****************************************************************************** ; LCD routines ;****************************************************************************** LCD_Init MOVLW 0x38 ; set 8 bit mode CALL LCD_Cmd MOVLW 0x0C ; turn cursor off CALL LCD_Cmd MOVLW 0x06 ; set display character mode CALL LCD_Cmd CALL Send_ClearScreen ; clear display RETLW 0x00 LCD_Cmd ; to send an instruction (in W) to the LCD BCF LCDControl,RegSel ; sending initiation parameters, 0 for instruction MOVWF PORTB ; put command data on port B CALL PULSE ; transmit RETURN PULSE ; transmit the data on port B to the Display BCF LCDControl,Enable CALL DELAY5 ; allow time to transmit BSF LCDControl,Enable RETLW 0x00 ;****************************************************************************** ; TEXT routines ;****************************************************************************** LCDTestScreen CALL Send_ClearScreen CALL Send_D ; 01 CALL Send_a ; 02 CALL Send_a ; 03 CALL Send_n ; 04 CALL Send_Space ; 05 CALL Send_e ; 06 CALL Send_n ; 07 CALL Send_Space ; 08 CALL Send_T ; 09 CALL Send_i ; 10 CALL Send_m ; 11 CALL Send_NextLineW ; CALL Send_T ; 01 CALL Send_e ; 02 CALL Send_s ; 03 CALL Send_t ; 04 CALL Send_i ; 05 CALL Send_n ; 06 CALL Send_g ; 07 CALL Send_Point ; 08 CALL Send_Point ; 09 CALL Send_Point ; 10 RETURN Screen_InsertCard CALL Send_ClearScreen CALL Send_Space ; 01 CALL Send_Space ; 02 CALL Send_P ; 03 CALL Send_l ; 04 CALL Send_e ; 05 CALL Send_a ; 06 CALL Send_s ; 07 CALL Send_e ; 08 CALL Send_Space ; 09 CALL Send_e ; 10 CALL Send_n ; 11 CALL Send_t ; 12 CALL Send_e ; 13 CALL Send_r ; 14 movlw 0x03 ; CALL Send_NextLineW ; move to 2nd row, 2nd column --> not really necessary CALL Send_y ; 04 CALL Send_o ; 05 CALL Send_u ; 06 CALL Send_r ; 07 CALL Send_Space ; 08 CALL Send_c ; 09 CALL Send_a ; 10 CALL Send_r ; 11 CALL Send_d ; 12 CALL Send_Exclamation ; 13 RETURN Screen_InProgress CALL Send_ClearScreen CALL Send_Space ; 01 CALL Send_Space ; 02 CALL Send_I ; 03 CALL Send_n ; 04 CALL Send_Space ; 05 CALL Send_P ; 06 CALL Send_r ; 07 CALL Send_o ; 08 CALL Send_g ; 09 CALL Send_r ; 10 CALL Send_e ; 11 CALL Send_s ; 12 CALL Send_s ; 13 movlw 0x00 ; 14 CALL Send_NextLineW RETURN Screen_CardRejected CALL Send_ClearScreen CALL Send_Space CALL Send_C ; 01 CALL Send_a ; 02 CALL Send_r ; 03 CALL Send_d ; 04 CALL Send_Space ; 05 CALL Send_R ; 06 CALL Send_e ; 07 CALL Send_j ; 08 CALL Send_e ; 09 CALL Send_c ; 10 CALL Send_t ; 11 CALL Send_e ; 12 CALL Send_d ; 13 CALL Send_Exclamation ; 14 movlw 0x02 ; 02 CALL Send_NextLineW ; move to 2nd row, 2nd column --> not really necessary CALL Send_R ; 03 CALL Send_e ; 04 CALL Send_m ; 05 CALL Send_o ; 06 CALL Send_v ; 07 CALL Send_e ; 08 CALL Send_Space ; 09 CALL Send_C ; 10 CALL Send_a ; 11 CALL Send_r ; 12 CALL Send_d ; 13 RETURN Screen_AccessDenied CALL Send_ClearScreen CALL Send_Space ; 01 CALL Send_A ; 02 CALL Send_c ; 03 CALL Send_c ; 04 CALL Send_e ; 05 CALL Send_s ; 06 CALL Send_s ; 07 CALL Send_Space ; 08 CALL Send_D ; 09 CALL Send_e ; 10 CALL Send_n ; 11 CALL Send_i ; 12 CALL Send_e ; 13 CALL Send_d ; 14 CALL Send_Exclamation ; 15 movlw 0x02 ; 02 CALL Send_NextLineW ; move to 2nd row, 2nd column --> not really necessary CALL Send_R ; 03 CALL Send_e ; 04 CALL Send_m ; 05 CALL Send_o ; 06 CALL Send_v ; 07 CALL Send_e ; 08 CALL Send_Space ; 08 CALL Send_C ; 09 CALL Send_a ; 10 CALL Send_r ; 11 CALL Send_d ; 12 RETURN Screen_AccessGranted CALL Send_ClearScreen CALL Send_Space ; 01 CALL Send_Space ; 02 CALL Send_Space ; 03 CALL Send_Space ; 04 CALL Send_W ; 05 CALL Send_e ; 06 CALL Send_l ; 07 CALL Send_c ; 08 CALL Send_o ; 09 CALL Send_m ; 10 CALL Send_e ; 11 movlw 0x00 ; 00 CALL Send_NextLineW ; move to 2nd row RETURN Screen_WrongSide CALL Send_ClearScreen CALL Send_Space ; 01 CALL Send_Space ; 02 CALL Send_Space ; 03 CALL Send_W ; 04 CALL Send_r ; 05 CALL Send_o ; 06 CALL Send_n ; 07 CALL Send_g ; 08 CALL Send_Space ; 09 CALL Send_S ; 10 CALL Send_i ; 11 CALL Send_d ; 12 CALL Send_e ; 13 movlw 0x03 ; 03 CALL Send_NextLineW ; move to 2nd row, 2nd column --> not really necessary CALL Send_F ; 04 CALL Send_l ; 05 CALL Send_i ; 06 CALL Send_p ; 07 CALL Send_Space ; 08 CALL Send_c ; 09 CALL Send_a ; 10 CALL Send_r ; 11 CALL Send_d ; 12 CALL Send_Exclamation ; 13 RETURN Screen_RemoveCard CALL Send_ClearScreen CALL Send_Space ; 01 CALL Send_P ; 02 CALL Send_l ; 03 CALL Send_e ; 04 CALL Send_a ; 05 CALL Send_s ; 06 CALL Send_e ; 07 CALL Send_Space ; 08 CALL Send_R ; 09 CALL Send_e ; 10 CALL Send_m ; 11 CALL Send_o ; 12 CALL Send_v ; 13 CALL Send_e ; 14 movlw 0x03 ; 03 CALL Send_NextLineW ; move to 2nd row, 2nd column --> not really necessary CALL Send_y ; 04 CALL Send_o ; 05 CALL Send_u ; 06 CALL Send_r ; 07 CALL Send_Space ; 08 CALL Send_c ; 09 CALL Send_a ; 10 CALL Send_r ; 11 CALL Send_d ; 12 CALL Send_Exclamation ; 13 RETURN Screen_WriteName MOVF DATAIN17,W CALL LCD_Char MOVF DATAIN16,W CALL LCD_Char MOVF DATAIN15,W CALL LCD_Char MOVF DATAIN14,W CALL LCD_Char MOVF DATAIN13,W CALL LCD_Char MOVF DATAIN12,W CALL LCD_Char MOVF DATAIN11,W CALL LCD_Char MOVF DATAIN10,W CALL LCD_Char MOVF DATAIN9,W CALL LCD_Char MOVF DATAIN8,W CALL LCD_Char MOVF DATAIN7,W CALL LCD_Char MOVF DATAIN6,W CALL LCD_Char MOVF DATAIN5,W CALL LCD_Char MOVF DATAIN4,W CALL LCD_Char MOVF DATAIN3,W CALL LCD_Char MOVF DATAIN2,W CALL LCD_Char MOVF DATAIN1,W CALL LCD_Char RETURN Screen_Welcome CALL Send_ClearScreen CALL Send_S ; 01 CALL Send_m ; 02 CALL Send_a ; 03 CALL Send_r ; 04 CALL Send_t ; 05 CALL Send_C ; 06 CALL Send_a ; 08 CALL Send_r ; 09 CALL Send_d ; 10 CALL Send_Space ; 11 CALL Send_R ; 12 CALL Send_e ; 13 CALL Send_a ; 14 CALL Send_d ; 15 CALL Send_e ; 16 CALL Send_r ; 17 movlw 0x01 ; 01 CALL Send_NextLineW ; move to 2nd row, 2nd column --> not really necessary CALL Send_b ; 02 CALL Send_y ; 03 CALL Send_Space ; 04 CALL Send_D ; 05 CALL Send_a ; 06 CALL Send_a ; 07 CALL Send_n ; 08 CALL Send_Space ; 09 MOVLW A'&' CALL LCD_Char ; 10 CALL Send_Space ; 11 CALL Send_T ; 12 CALL Send_i ; 13 CALL Send_m ; 14 CALL DELAY_1000 CALL DELAY_1000 CALL DELAY_1000 RETURN ; End LCD textroutines ; Begin display text (alphabet, numbers, signs) Send_A MOVLW A'A' GOTO LCD_Char Send_B MOVLW A'B' GOTO LCD_Char Send_C MOVLW A'C' GOTO LCD_Char Send_D MOVLW A'D' GOTO LCD_Char Send_E MOVLW A'E' GOTO LCD_Char Send_F MOVLW A'F' GOTO LCD_Char Send_G MOVLW A'G' GOTO LCD_Char Send_H MOVLW A'H' GOTO LCD_Char Send_I MOVLW A'I' GOTO LCD_Char Send_J MOVLW A'J' GOTO LCD_Char Send_K MOVLW A'K' GOTO LCD_Char Send_L MOVLW A'L' GOTO LCD_Char Send_M MOVLW A'M' GOTO LCD_Char Send_N MOVLW A'N' GOTO LCD_Char Send_O MOVLW A'O' GOTO LCD_Char Send_P MOVLW A'P' GOTO LCD_Char Send_Q MOVLW A'Q' GOTO LCD_Char Send_R MOVLW A'R' GOTO LCD_Char Send_S MOVLW A'S' GOTO LCD_Char Send_T MOVLW A'T' GOTO LCD_Char Send_U MOVLW A'U' GOTO LCD_Char Send_V MOVLW A'V' GOTO LCD_Char Send_W MOVLW A'W' GOTO LCD_Char Send_X MOVLW A'X' GOTO LCD_Char Send_Y MOVLW A'Y' GOTO LCD_Char Send_Z MOVLW A'Z' GOTO LCD_Char Send_a MOVLW A'a' GOTO LCD_Char Send_b MOVLW A'b' GOTO LCD_Char Send_c MOVLW A'c' GOTO LCD_Char Send_d MOVLW A'd' GOTO LCD_Char Send_e MOVLW A'e' GOTO LCD_Char Send_f MOVLW A'f' GOTO LCD_Char Send_g MOVLW A'g' GOTO LCD_Char Send_h MOVLW A'h' GOTO LCD_Char Send_i MOVLW A'i' GOTO LCD_Char Send_j MOVLW A'j' GOTO LCD_Char Send_k MOVLW A'k' GOTO LCD_Char Send_l MOVLW A'l' GOTO LCD_Char Send_m MOVLW A'm' GOTO LCD_Char Send_n MOVLW A'n' GOTO LCD_Char Send_o MOVLW A'o' GOTO LCD_Char Send_p MOVLW A'p' GOTO LCD_Char Send_q MOVLW A'q' GOTO LCD_Char Send_r MOVLW A'r' GOTO LCD_Char Send_s MOVLW A's' GOTO LCD_Char Send_t MOVLW A't' GOTO LCD_Char Send_u MOVLW A'u' GOTO LCD_Char Send_v MOVLW A'v' GOTO LCD_Char Send_w MOVLW A'w' GOTO LCD_Char Send_x MOVLW A'x' GOTO LCD_Char Send_y MOVLW A'y' GOTO LCD_Char Send_z MOVLW A'z' GOTO LCD_Char Send_0 MOVLW A'0' GOTO LCD_Char Send_1 MOVLW A'1' GOTO LCD_Char Send_2 MOVLW A'2' GOTO LCD_Char Send_3 MOVLW A'3' GOTO LCD_Char Send_4 MOVLW A'4' GOTO LCD_Char Send_5 MOVLW A'5' GOTO LCD_Char Send_6 MOVLW A'6' GOTO LCD_Char Send_7 MOVLW A'7' GOTO LCD_Char Send_8 MOVLW A'8' GOTO LCD_Char Send_9 MOVLW A'9' GOTO LCD_Char Send_Space MOVLW A' ' GOTO LCD_Char Send_Question MOVLW A'?' GOTO LCD_Char Send_Point MOVLW A'.' GOTO LCD_Char Send_Dubbel MOVLW A':' GOTO LCD_Char Send_Minus MOVLW A'-' GOTO LCD_Char Send_Plus MOVLW A'+' GOTO LCD_Char Send_Exclamation MOVLW A'!' GOTO LCD_Char Send_Dollar MOVLW B'00100100' GOTO LCD_Char LCD_Char ; Send character (in W) to LCD BSF LCDControl,RegSel ; sending initiation parameters, 1 for character data MOVWF PORTB ; put character data on port B CALL PULSE ; transmit RETURN Send_ClearScreen MOVLW B'00000001' ; Clear Display CALL LCD_Cmd MOVLW B'00000010' ; Go to Home CALL LCD_Cmd RETURN Send_Line MOVLW B'10000000' ; Goto Next Line CALL LCD_Cmd RETURN Send_LineW ADDLW B'10000000' ; move to 2nd row, column W CALL LCD_Cmd RETURN Send_NextLine MOVLW B'11000000' ; Goto Next Line CALL LCD_Cmd RETURN Send_NextLineW ADDLW B'11000000' ; move to 2nd row, column W CALL LCD_Cmd RETURN ;****************************************************************************** ; DELAY routines ;***************************************************************************** DELAY_1000 MOVLW D'3' ; approx 1 sec delay MOVWF TIMER3 DEL_LOOP0 MOVLW D'250' MOVWF TIMER2 DEL_LOOP1 MOVLW D'255' MOVWF TIMER1 DEL_LOOP2 DECFSZ TIMER1,F GOTO DEL_LOOP2 DECFSZ TIMER2,F GOTO DEL_LOOP1 DECFSZ TIMER3,F GOTO DEL_LOOP0 RETLW 0 DELAY255 ; delay 255 ms MOVLW 0xff ; 255 GOTO d0 DELAY100 ; delay 100ms MOVLW 0x54 ; 100 GOTO d0 DELAY50 ; delay 50ms MOVLW 0x32 ; 50 GOTO d0 DELAY10 ; delay 10ms MOVLW 0x0a ; 10 GOTO d0 DELAY5 ; delay 5ms MOVLW 0x05 ; 5 5 d0 MOVWF COUNT1 ; delay 1ms d1 MOVLW 0xC7 ; 199 MOVWF COUNTa MOVLW 0x01 ; 1 MOVWF COUNTb DELAY_0 DECFSZ COUNTa, F GOTO $+2 DECFSZ COUNTb, F GOTO DELAY_0 DECFSZ COUNT1, F GOTO d1 RETLW 0x00 DELAY_MICROS ; Clk 2Mhz -> etu = 372/f = 186 microsec ;; 3W+4 = #instructies = #microsx2 => W = (#microsx2-4)/3 ; Call & Return included MOVWF TIMER3 DELAY_MICROS_LOOP DECFSZ TIMER3 GOTO DELAY_MICROS_LOOP RETURN ;****************************************************************************** ; SERIAL PORT Routines ;***************************************************************************** SetupSerial Bank1 ; select file register bank 1 BCF TRISC, 0x06 ; make RC6 - TX pin an output BSF TRISC, 0x07 ; make RC7 - RX pin an input BCF TXSTA, BRGH ; select low speed mode MOVLW D'25' MOVWF SPBRG ; select baud rate 2400 in low speed BCF TXSTA, SYNC ; select async mode BSF TXSTA, TXEN ; enable Transmit Bank0 ; select file register bank 0 MOVLW 0x90 ; enable serial port and reception MOVWF RCSTA MOVLW 0xc0 ; enable global and peripheral ints MOVWF INTCON Bank1 ; select file register bank 1 MOVLW 0x20 ; (0x30 enable TX) and RX interrupts MOVWF PIE1 Bank0 ; select file register bank 0 RETURN SendSerial ; Send a Byte in W to PC BTFSS PIR1,4 ; wait for bit 4=1 (showingTXREG empty) GOTO SendSerial NOP MOVWF TXREG ; put val in TXREG ready for auto-txmit RETURN ; Get received data from PC GetData Bank0 ; select file register bank 0 BTFSC RCSTA, OERR ; test overrun error flag GOTO ErrOERR ; handle it if error BTFSC RCSTA, FERR ; test framing error flag GOTO ErrFERR ; handle it if error MOVF DATAIN17, W ; move last received data MOVWF DATAIN18 MOVF DATAIN16, W ; move last received data MOVWF DATAIN17 MOVF DATAIN15, W ; move last received data MOVWF DATAIN16 MOVF DATAIN14, W ; move last received data MOVWF DATAIN15 MOVF DATAIN13, W ; move last received data MOVWF DATAIN14 MOVF DATAIN12, W ; move last received data MOVWF DATAIN13 MOVF DATAIN11, W ; move last received data MOVWF DATAIN12 MOVF DATAIN10,W ; move last received data MOVWF DATAIN11 MOVF DATAIN9, W ; move last received data MOVWF DATAIN10 MOVF DATAIN8, W ; move last received data MOVWF DATAIN9 MOVF DATAIN7, W ; move last received data MOVWF DATAIN8 MOVF DATAIN6, W ; move last received data MOVWF DATAIN7 MOVF DATAIN5, W ; move last received data MOVWF DATAIN6 MOVF DATAIN4, W ; move last received data MOVWF DATAIN5 MOVF DATAIN3, W ; move last received data MOVWF DATAIN4 MOVF DATAIN2, W ; move last received data MOVWF DATAIN3 MOVF DATAIN1, W ; move last received data MOVWF DATAIN2 MOVF RCREG, W ; get received data MOVWF DATAIN1 ; copy to DataIn1 XORLW 0x00 ; if W is zero, end of data reached BTFSS STATUS, Z ; Z=1 when XOR gave zero GOTO BlockNotComplete ; ALL Data Received, do stuff with it CALL ProcessAccessData BlockNotComplete GOTO EndInt ;****************************************************************************** ; Read analog data and transmit to PC PutData GOTO EndInt ;****************************************************************************** ; Error because OERR overrun error bit is set - clear and continue ErrOERR BCF RCSTA, CREN ; reset the receiver logic BSF RCSTA, CREN ; enable reception again GOTO EndInt ; Error because FERR framing error bit is set - clear and continue ErrFERR MOVF RCREG, W ; discard received data that has error GOTO EndInt ;****************************************************************************** ; INTERRUPT HANDLING ;****************************************************************************** Int MOVWF WREG_TEMP ; save WREG MOVF STATUS, W ; store STATUS in WREG CLRF STATUS ; select file register bank 0 MOVWF STATUS_TEMP ; save STATUS value MOVF PCLATH, W ; store PCLATH in WREG MOVWF PCLATH_TEMP ; save PCLATH value CLRF PCLATH ; select program memory page0 MOVF FSR, W ; store FSR in WREG MOVWF FSR_TEMP ; save FSR value Bank0 ; select file register bank 0 BTFSC PIR1, RCIF ; test RCIF receive interrupt BSF STATUS, RP0 ; change to bank 1 if RCIF set BTFSC PIE1, RCIE ; test if interrupt enabled if RCIF set GOTO GetData ; if RCIF and RCIE set, do receive Bank0 ; select file register bank 0 BTFSC PIR1, TXIF ; test for TXIF transmit interrupt BSF STATUS, RP0 ; change to bank 1 if TXIF set BTFSC PIE1, TXIE ; test if interrupt enabled if TXIF set GOTO PutData ; if TXIF and TCIE set, do transmit ; can do special error handling here - an unexpected interrupt occurred EndInt Bank0 ; select file register bank 0 MOVF FSR_TEMP, W ; get saved FSR value MOVWF FSR ; restore FSR MOVF PCLATH_TEMP, W ; get saved PCLATH value MOVWF PCLATH ; restore PCLATH MOVF STATUS_TEMP, W ; get saved STATUS value MOVWF STATUS ; restore STATUS SWAPF WREG_TEMP, F ; prepare WREG to be restored SWAPF WREG_TEMP, W ; restore WREG without affecting STATUS RETFIE ; return from interrupt ;****************************************************************************** ClearVariables CLRF TS CLRF T0 CLRF TA1 CLRF TB1 CLRF TC1 CLRF TD1 CLRF TA2 CLRF TB2 CLRF TC2 CLRF TD2 CLRF TA3 CLRF TB3 CLRF TC3 CLRF TD3 CLRF DATAIN1 CLRF DATAIN2 CLRF DATAIN3 CLRF DATAIN4 CLRF DATAIN5 CLRF DATAIN6 CLRF DATAIN7 CLRF DATAIN8 CLRF DATAIN9 CLRF DATAIN10 CLRF DATAIN11 CLRF DATAIN12 CLRF DATAIN13 CLRF DATAIN14 CLRF DATAIN15 CLRF DATAIN16 CLRF DATAIN17 CLRF DATAIN18 GOTO Int RETURN END ; End Smartcard Reader Program