Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Not getting proper output for text file encryption

Status
Not open for further replies.

ganavel9783

Member level 1
Joined
Sep 6, 2005
Messages
38
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
2,257
Hi people,

I recently posted a thread about data truncation problem with text file encryption. I overcame the problem by placing a delay function(sleep) in my pc application.

However when i tried to encrypt a plain text file, i notice that sometimes there are missing bytes(1,2,3 or more sometimes) for the encrypted text.So surely the decrypted text is not going to be same as the original text. Here is an example of the text files for the encryption and also decryption.

key used for both encryption & decryption:waltwhitman,poet

plain text (106 bytes):

I pass death with the dying and birth with new washed baby, and am not contained between my hat and boots.

encrypted text (111 bytes):

·ç~Pɲ¼”äriÁ7÷è‰wíÿK=:r5oéÎKFÂ6’ßú†Í-!ºDfbÆü{ßӍiGÃ|ÓœëxÎåEسՙ¿U™™iªÁú d‚0ã~åà bü²à‘úCä̆ës¯÷K
ä

decrypted text(111 bytes):

I pass death with the dying and birth with nè8Ýà»P—ML!¥þ€|±^àTNä±¼WSÙÇ»öXÞŸ…iˆ{æã¯uœ?c‰ÙjF¨ÍSˆ„§8ÚÜPIÕn

My pc application sends the 16 byte key followed by a special a non-printable ascii character to distinguish key data and the next 16 byte data (original text or encrypted text) is send followed by a special character. Here is an example:

<16 byte key><1 byte BEL character><16 byte original text><1 byte carriage return character>[delay for 5 ms]<16 byte original text><1 byte carriage return character>[delay for 5 ms]<16 byte original text><1 byte carriage return character>[delay for 5 ms]

This will continue until all the 16 byte blocks of the plain text file is fully encrypted.

To get the the original text, decryption is done.my pc application send the encrypted text by this manner:

<16 byte key><1 byte BEL character><16 byte encrypted text><1 byte line feed character>[delay for 6 ms]<16 byte encrypted text><1 byte line feed character>[delay for 6 ms]<16 byte encrypted text><1 byte line feed character>[delay for 6 ms]

This will continue until all the 16 byte blocks of the encrypted text file is fully decrypted.

For ur information i'm using the AES algorithm which i've implemented into PIC16f877 using UART full duplex mode.

As u can c, the encrypted text is suppose to be 112 bytes. Since the last 16 byte block for the plain text is incomplete, it is padded with space characters to make it into a full block of 16 bytes.

I do realise that encrypting and decrypting a 16 byte block data does take time(about 1.0546 ms for encryption and 1.4682 ms for decryption). Thats the reason i place a delay in my GUI so that i send the next 16 byte block data once the previous 16 byte block data is either encrypted or decrypted and send back to PC.I tried reviewing my .asm code for PIC16f877 chip that i'm using and i also looked into the bauda rates and the ext oscillator but i'm still having this missing byte problem. Its also strange that it works sometimes with different keys.

So my questions are:

1) y is there missing bytes even though i've placed a delay in my GUI?

2) How many bytes can serial port support to transfer large text files?

3) Is there any solution to my problems?

The .asm file that i've used for my chip shown below. U can run through the code in MPLAB n c it for urself.Its kinda long:-(.

Regards,

ganavel9783

Code:
;=============================================================================
;	Filename:	AES.asm
;=============================================================================
;	Author: 	ganavel9783
;	Company:	Home
;	Revision:	1.00
;	Date:		28th February, 2006
;	Last Revised:	29th March,2006
;	Assembled using MPLAB V7.20(QuickBuild Option)
;=============================================================================
;	Include Files:	p16f877.inc	V1.12
;=============================================================================
;	This code uses USART implementation with transmit and receive 
;	interrupts.Received data is put into a buffer, called RxBuffer. When a
;	non printable ASCII character(<CR> for encrypt or <LF> for decrypt)is 
;	received,the received data in RxBuffer is either encrypted or 
;	decrypted using the Advanced Encryption Standard(AES) algorithm before
;	being moved into another buffer,called TxBuffer. The data in TxBuffer 
;	is then transmitted.Besides that, there are 2 types of key buffer 
;	(constant and overwritten). Constant key buffer is called KeyBuffer 
;	while another key buffer that is overwritten during the period of
;	encryption is called key. This key data is distinguished by detecting 
;	a <BEL> character.This code is a combination of codes from 
;	Microchip's P16_tiri.asm(Application Note 774) and aes_rijn.asm
;	(Application Note 821).
;=============================================================================

		list p=16f877		;list directive to define processor
		#include <p16f877.inc>	;processor specific definitions
		errorlevel -302		;suppress "not in bank 0" message

		__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_OFF & _LVP_OFF & _DEBUG_OFF & _CPD_OFF

;----------------------------------------------------------------------------
;Constants

SPBRG_VAL	EQU	.65		;set baud rate 19200 for 20.228Mhz clock
TX_BUF_LEN	EQU	.16		;length of transmit circular buffer
RX_BUF_LEN	EQU	TX_BUF_LEN	;length of receive circular buffer
KEY_BUF_LEN	EQU	TX_BUF_LEN	;user input key buffer
ROUNDS		equ	0x0A		;number of rounds necessary to cipher/decipher
INIT_RAM0	equ	0x20		;Starting point of RAM in segment 0
INIT_RAM1	equ	0xA0		;Starting point of RAM in segment 1
INIT_RAM2	equ	0x30		;Starting point of RAM in segment 2
;----------------------------------------------------------------------------
;Bit Definitions for Flags Register

TxBufFull	EQU	0		;bit indicates Tx buffer is full
TxBufEmpty	EQU	1		;bit indicates Tx buffer is empty
RxBufFull	EQU	2		;bit indicates Rx buffer is full
RxBufEmpty	EQU	3		;bit indicates Rx buffer is empty
ReceivedCR	EQU	4		;bit indicates <CR> character received(Encrypt)
ReceivedLF	EQU	5		;bit indicates <LF> character recieved(Decrypt)

;----------------------------------------------------------------------------
;Bit Definitions for Flags2 Register

KeyBufFull	EQU	0		;bit indicates Key buffer is full
KeyBufEmpty	EQU	1		;bit indicates Key buffer is empty
ReceivedBEL	EQU	2		;bit indicates <BEL> character received(Key Set Up)
;----------------------------------------------------------------------------
;Variables
		
		
		
		CBLOCK	0x70
		WREG_TEMP		;storage for WREG during interrupt
		STATUS_TEMP		;storage for STATUS during interrupt
		PCLATH_TEMP		;storage for PCLATH during interrupt
		FSR_TEMP		;storage for FSR during interrupt
		ENDC

		CBLOCK	0x20
		Flags			;byte to store indicator flags
		Flags2			;byte to store indicator flags for key
		TempData		;temporary data in main routines 
		BufferData		;temporary data in buffer routines 
		TxStartPtr		;pointer to start of data in TX buffer
		TxEndPtr		;pointer to end of data in TX buffer
		RxStartPtr		;pointer to start of data in RX buffer
		RxEndPtr		;pointer to end of data in RX buffer
		KeyStartPtr		;pointer to start of data in Key2 buffer
		KeyEndPtr		;pointer to end of data in Key2 buffer
		TestFlagsReg		;Flags & Flags2 register indicator for 
		ENDC			;cipher text data(decrypt)

		CBLOCK	0x140
		aux			;general purpose variables
		aux1
		aux2
		aux3		
		ENDC
		
		CBLOCK	0x144
		round_counter		;encryption/decryption rounds counter	
		rcon		
		ENDC

		CBLOCK	0x14A
		d0		
		d1	
		d2		
		ENDC
				
		CBLOCK	0xA0
		TxBuffer:TX_BUF_LEN	;transmit data buffer
		ENDC

		CBLOCK	0x150
		RxBuffer:RX_BUF_LEN	;receive data buffer
		ENDC
		
block equ RxBuffer	;block vector (16 bytes*8=>128 bits)
	
		CBLOCK 0x130
		KeyBuffer:KEY_BUF_LEN	;constant key from user input
		ENDC

		CBLOCK 0x160
		key:KEY_BUF_LEN	;key vector (16 bytes*8=>128 bits)
		ENDC			;overwritten during ecryption & decryption	
			

	
;-----------------------------------------------------------------------------
;Macros to select the register bank
;Many bank changes can be optimized when only one STATUS bit changes

Bank0		MACRO			;macro to select data RAM bank 0
		bcf	STATUS,IRP
		bcf	STATUS,RP0
		bcf	STATUS,RP1
		ENDM

Bank1		MACRO			;macro to select data RAM bank 1
		bcf	STATUS,IRP
		bsf	STATUS,RP0
		bcf	STATUS,RP1
		ENDM

Bank2		MACRO			;macro to select data RAM bank 2
		bsf	STATUS,IRP
		bcf	STATUS,RP0
		bsf	STATUS,RP1
		ENDM

Bank3		MACRO			;macro to select data RAM bank 3
		bsf	STATUS,IRP
		bsf	STATUS,RP0
		bsf	STATUS,RP1
		ENDM

;----------------------------------------------------------------------------
;This code executes when a reset occurs.

		ORG     0x0000		;place code at reset vector

ResetCode:	clrf    PCLATH		;select program memory page 0
  		goto    Main		;go to beginning of program

;----------------------------------------------------------------------------
;This code executes when an interrupt occurs.

		ORG	0x0004		;place code at interrupt vector

InterruptCode:	movwf	WREG_TEMP	;save WREG
		movf	STATUS,W	;store STATUS in WREG
		clrf	STATUS		;select file register bank0
		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

		;test other interrupt flags here

		Bank0			;select bank0
		btfsc	PIR1,RCIF	;test RCIF receive interrupt
		bsf	STATUS,RP0	;change to bank1 if RCIF set
		btfsc	PIE1,RCIE	;test if interrupt enabled if RCIF set
		goto	GetData		;if RCIF and RCIE set, do receive

		Bank0			;select bank0
		btfsc	PIR1,TXIF	;test for TXIF transmit interrupt
		bsf	STATUS,RP0	;change to bank1 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 

		goto	EndInt

;------------------------------------
;Get received data and write into receive buffer.

GetData:	Bank0
		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

		btfsc	Flags,RxBufFull	;check if buffer full
		goto	ErrRxOver	;handle it if full

		movf	RCREG,W		;get received data
		call	PutRxBuffer	;and put in buffer
		goto	EndInt

;error because OERR overrun error bit is set
;can do special error handling here - this code simply clears and continues

ErrOERR:	bcf	RCSTA,CREN	;reset the receiver logic
		bsf	RCSTA,CREN	;enable reception again
		goto	EndInt

;error because FERR framing error bit is set
;can do special error handling here - this code simply clears and continues

ErrFERR:	movf	RCREG,W
		goto	EndInt

;error because receive buffer is full and new data has been received
;can do special error handling here - this code simply receives data
;and test to distiguish type of data and later discards the data
;and continues

ErrRxOver:	clrf	TestFlagsReg
		movf	RCREG,W		;discard received data that has error
		movwf	TestFlagsReg	;place received data to TestFlags2Reg
		movf	TestFlagsReg,W	;distinguish type of data received
		xorlw	0x07		;compare with <BEL>
		btfsc	STATUS,Z	;check if the same
		bsf	Flags2,ReceivedBEL;indicate <BEL> character received
		xorlw	0x07		;change back to valid data
		xorlw	0x0d		;compare with <CR>
		btfsc	STATUS,Z	;check if the same
		bsf	Flags,ReceivedCR;indicate <CR> character received
		xorlw	0x0d		;change back to valid data
		xorlw	0x0a		;compare with <LF>
		btfsc	STATUS,Z	;check if the same
		bsf	Flags,ReceivedLF;indicate <LF> character received
		goto	EndInt

;------------------------------------
;Read data from the transmit buffer and transmit the data.

PutData:	Bank0			;select bank 0
		btfss	Flags,TxBufEmpty ;check if transmit buffer empty
		goto	PutDat1		;if not then go get data and transmit
		Bank1			;select bank1
		bcf	PIE1,TXIE	;disable TX interrupt because all done
		goto	EndInt

PutDat1:	call	GetTxBuffer	;get data to transmit
		movwf	TXREG		;and transmit

;------------------------------------
;End of interrupt routine restores context

EndInt:		Bank0			;select 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

;----------------------------------------------------------------------------
;Main routine to clear ram locations,check for reception of <CR>,<LF> and <BEL>
;to distinguish plaintext data,ciphertext data and key data and calls a routine
;to move the data to transmit back.

Main:		call	init_cpu0	;start CPU registers
		call	init_cpu1
		call	init_cpu2
		call	SetupSerial	;set up serial port and buffers
		goto	MainLoop
init_cpu0:	Bank0			;clear RAM(0x0020-0x007f)in bank0
		movlw	INIT_RAM0	;points to the start of RAM0
		movwf	FSR
CleanB0:    	clrf	INDF		;clear RAM location pointed by FSR
		incf	FSR,F		;increment pointer
		btfss	FSR,7		;while FSR<0x80 loop
		goto	CleanB0
		return
		
init_cpu1:	Bank1			;clear RAM(0x00A0-0x00Af)in bank1	
		movlw	INIT_RAM1	;points to the start of RAM1
		movwf	FSR	
CleanB1:	clrf	INDF		;clear RAM location pointed by FSR
		incf	FSR,F		;increment pointer
		btfss	FSR,4		;while FSR<0x10 loop
		goto	CleanB1
	        return	

init_cpu2:	Bank2			;clear RAM(0x0130-0x017f)in bank2
		movlw	INIT_RAM2	;points to the start of RAM2
		movwf	FSR
CleanB2:	clrf	INDF		;clear RAM location pointed by FSR
		incf	FSR,F		;increment pointer
		btfss	FSR,7		;while FSR<0x80 loop
		goto	CleanB2
		return
		
		;do other initialization here

MainLoop:	Bank0			;select bank0
		btfsc	Flags2,ReceivedBEL;check if <BEL> character received
		call	CopyKey		;if so the move received data to key buffer
		btfsc	Flags,ReceivedCR;check if <CR> character received
		call	CopyENC		;if so then encrypt received data and move 
					;to TX Buffer
		btfsc	Flags,ReceivedLF;check if <LF> character received
		call	CopyDEC		;if so the decrypt received data and move 
					;to TX Buffer
		;do other stuff here		

		goto	MainLoop	;repeat main loop to check for data

;----------------------------------------------------------------------------
;Set up serial port and buffers.

SetupSerial:	Bank1			;select bank 1
		movlw	0xc0		;set tris bits for TX and RX
		iorwf	TRISC,F
		movlw	SPBRG_VAL	;set baud rate
		movwf	SPBRG
		movlw	0x24		;enable transmission and high baud rate
		movwf	TXSTA
		Bank0			;select bank0
		movlw	0x90		;enable serial port and reception
		movwf	RCSTA
		call	InitTxBuffer	;initialize transmit buffer
		call	InitRxBuffer	;initialize receive buffer
		call	InitKeyBuffer
		movlw	0xc0		;enable global and peripheral ints
		movwf	INTCON
		Bank1			;select bank1
		movlw	0x30		;enable TX and RX interrupts
		movwf	PIE1
		return

;----------------------------------------------------------------------------
;Circular buffer routines.

;----------------------------------------------------------------------------
;Initialize transmit buffer

InitTxBuffer:	Bank0
		movlw	LOW TxBuffer	;take address of transmit buffer
		movwf	TxStartPtr	;and place in transmit start pointer
		movwf	TxEndPtr	;and place in transmit end pointer
		bcf	Flags,TxBufFull	;indicate Tx buffer is not full
		bsf	Flags,TxBufEmpty ;indicate Tx buffer is empty
		return

;----------------------------------------------
;Initialize receive buffer

InitRxBuffer:	Bank0
		movlw	LOW RxBuffer	;take address of receive buffer
		movwf	RxStartPtr	;and place in receive start pointer
		movwf	RxEndPtr	;and place in receive end pointer
		bcf	Flags,RxBufFull	;indicate Rx buffer is not full
		bsf	Flags,RxBufEmpty ;indicate Rx buffer is empty
		return

;----------------------------------------------
;Initialize Key buffer

InitKeyBuffer:	Bank0
		movlw	LOW KeyBuffer	;take address of key buffer
		movwf	KeyStartPtr	;and place in receive start pointer
		movwf	KeyEndPtr	;and place in receive end pointer
		bcf	Flags2,KeyBufFull;indicate Key buffer is not full
		bsf	Flags2,KeyBufEmpty ;indicate Key buffer is empty
		return
;----------------------------------------------
;Add a byte (from WREG) to the end of the key buffer

PutKeyBuffer:	
		Bank0			;select bank 0
		btfsc	Flags2,KeyBufFull;check if buffer full
		goto	ErrKeyBufFull	;and go handle error if full

		BANKISEL KeyBuffer	;bank bit for indirect addressing
		movwf	BufferData	;save WREG data into BufferData
		movf	KeyEndPtr,W	;get EndPointer
		movwf	FSR		;and place into FSR
		movf	BufferData,W	;get BufferData
		movwf	INDF		;and store in buffer

;test if buffer pointer needs to wrap around to beginning of buffer memory

		movlw	LOW KeyBuffer+KEY_BUF_LEN-1 ;get last address of buffer
		xorwf	KeyEndPtr,W	;and compare with end pointer
		movlw	LOW KeyBuffer	;load first address of buffer
		btfss	STATUS,Z	;check if pointer is at last address
		incf	KeyEndPtr,W	;if not then increment pointer
		movwf	KeyEndPtr	;store new end pointer value

;test if buffer is full

		subwf	KeyStartPtr,W	;compare with start pointer
		btfsc	STATUS,Z	;check if the same
		bsf	Flags2,KeyBufFull;if so then indicate buffer full
		bcf	Flags2,KeyBufEmpty ;buffer cannot be empty
		Bank0			;select bank 0
		return

;error because attempting to store new data and the buffer is full
;can do special error handling here - this code simply ignores the byte

ErrKeyBufFull:	Bank0
		return 			;no save of data because buffer full

;----------------------------------------------
;Add a byte (from WREG) to the end of the transmit buffer

PutTxBuffer:	Bank1			;select bank 1
		bcf	PIE1,TXIE	;disable transmit interrupt
		Bank0			;select bank 0
		btfsc	Flags,TxBufFull	;check if buffer full
		goto	ErrTxBufFull	;and go handle error if full

		BANKISEL TxBuffer	;bank bit for indirect addressing
		movwf	BufferData	;save WREG data into BufferData
		movf	TxEndPtr,W	;get EndPointer
		movwf	FSR		;and place into FSR
		movf	BufferData,W	;get BufferData
		movwf	INDF		;and store in buffer

;test if buffer pointer needs to wrap around to beginning of buffer memory

		movlw	LOW TxBuffer+TX_BUF_LEN-1 ;get last address of buffer
		xorwf	TxEndPtr,W	;and compare with end pointer
		movlw	LOW TxBuffer	;load first address of buffer
		btfss	STATUS,Z	;check if pointer is at last address
		incf	TxEndPtr,W	;if not then increment pointer
		movwf	TxEndPtr	;store new end pointer value

;test if buffer is full

		subwf	TxStartPtr,W	;compare with start pointer
		btfsc	STATUS,Z	;check if the same
		bsf	Flags,TxBufFull	;if so then indicate buffer full
		bcf	Flags,TxBufEmpty ;buffer cannot be empty
		Bank1			;select bank 1
		bsf	PIE1,TXIE	;enable transmit interrupt
		Bank0			;select bank 0
		return

;error because attempting to store new data and the buffer is full
;can do special error handling here - this code simply ignores the byte

ErrTxBufFull:	Bank1			;select bank 1
		bsf	PIE1,TXIE	;enable transmit interrupt
		Bank0			;select bank 0
		return 			;no save of data because buffer full

;----------------------------------------------
;Add a byte (from WREG) to the end of the receive buffer

PutRxBuffer:	Bank0			;select bank 0
		btfsc	Flags,RxBufFull	;check if buffer full
		goto	ErrRxBufFull	;and go handle error if full

		BANKISEL RxBuffer	;bank bit for indirect addressing
		movwf	BufferData	;save WREG into BufferData
		movf	RxEndPtr,W	;get EndPointer
		movwf	FSR		;and place into FSR
		movf	BufferData,W	;get BufferData
		movwf	INDF		;store in buffer

;test if buffer pointer needs to wrap around to beginning of buffer memory

		movlw	LOW RxBuffer+RX_BUF_LEN-1 ;get last address of buffer
		xorwf	RxEndPtr,W	;and compare with end pointer
		movlw	LOW RxBuffer	;load first address of buffer
		btfss	STATUS,Z	;check if pointer is at last address
		incf	RxEndPtr,W	;if not then increment pointer
		movwf	RxEndPtr	;store new end pointer value

;test if buffer is full

		subwf	RxStartPtr,W	;compare with start pointer
		btfsc	STATUS,Z	;check if the same
		bsf	Flags,RxBufFull	;if so then indicate buffer full
		bcf	Flags,RxBufEmpty ;buffer cannot be empty
		return

;error because attempting to store new data and the buffer is full
;can do special error handling here - this code simply ignores the byte

ErrRxBufFull:	return 			;no save of data because buffer full

;----------------------------------------------
;Remove and return (in WREG) the byte at the start of the transmit buffer

GetTxBuffer:	Bank0			;select bank 0
		btfsc	Flags,TxBufEmpty ;check if transmit buffer empty
		goto	ErrTxBufEmpty	;and go handle error if empty

		BANKISEL TxBuffer	;bank bit for indirect addressing
		movf	TxStartPtr,W	;get StartPointer
		movwf	FSR		;and place into FSR

;test if buffer pointer needs to wrap around to beginning of buffer memory

		movlw	LOW TxBuffer+TX_BUF_LEN-1 ;get last address of buffer
		xorwf	TxStartPtr,W	;and compare with start pointer
		movlw	LOW TxBuffer	;load first address of buffer
		btfss	STATUS,Z	;check if pointer is at last address
		incf	TxStartPtr,W	;if not then increment pointer
		movwf	TxStartPtr	;store new pointer value
		bcf	Flags,TxBufFull	;buffer cannot be full

;test if buffer is now empty

		xorwf	TxEndPtr,W	;compare start to end	
		btfsc	STATUS,Z	;check if the same
		bsf	Flags,TxBufEmpty ;if same then buffer will be empty
		movf	INDF,W		;get data from buffer

		return

;error because attempting to read data from an empty buffer
;can do special error handling here - this code simply returns zero

ErrTxBufEmpty:	retlw	0		;tried to read empty buffer

;----------------------------------------------
;Remove and return (in WREG) the byte at the start of the receive buffer

GetRxBuffer:	Bank0			;select bank 0
		btfsc	Flags,RxBufEmpty ;check if receive buffer empty
		goto	ErrRxBufEmpty	;and go handle error if empty

		Bank1			;select bank 1
		bcf	PIE1,RCIE	;disable receive interrupt
		Bank0			;select bank 0

		BANKISEL RxBuffer	;bank bit for indirect addressing
		movf	RxStartPtr,W	;get StartPointer
		movwf	FSR		;and place into FSR

;test if buffer pointer needs to wrap around to beginning of buffer memory

		movlw	LOW RxBuffer+RX_BUF_LEN-1 ;get last address of buffer
		xorwf	RxStartPtr,W	; and compare with start pointer
		movlw	LOW RxBuffer	;load first address of buffer
		btfss	STATUS,Z	;check if pointer is at last address
		incf	RxStartPtr,W	;if not then increment pointer
		movwf	RxStartPtr	;store new pointer value
		bcf	Flags,RxBufFull	;buffer cannot be full

;test if buffer is now empty

		xorwf	RxEndPtr,W	;compare start to end	
		btfsc	STATUS,Z	;check if the same
		bsf	Flags,RxBufEmpty ;if same then buffer will be empty
		movf	INDF,W		;get data from buffer

		Bank1			;select bank 1
		bsf	PIE1,RCIE	;enable receive interrupt
		Bank0			;select bank 0
		return

;error because attempting to read data from an empty buffer
;can do special error handling here - this code simply returns zero

ErrRxBufEmpty:	Bank1			;select bank 1
		bsf	PIE1,RCIE	;enable receive interrupt
		Bank0			;select bank 0
		retlw	0		;tried to read empty buffer

;----------------------------------------------------------------------------
;Get receive buffer data and move to Key buffer 
		
CopyKey:	Bank0			;select bank 0
		bcf	Flags2,ReceivedBEL ;clear <BEL> received indicator
Copy1:		btfsc	Flags,RxBufEmpty ;check if Rx buffer is empty
		return			;if so then return
		call	GetRxBuffer	;get data from receive buffer
		call	PutKeyBuffer	;put data in transmit buffer
		goto	Copy1		;if not the same then move another byte
		
;----------------------------------------------------------------------------
;Encrypt receive buffer data and move to transmit buffer 
		
CopyENC:	Bank0			;select bank 2
		movlw	0xa0		;take address of transmit buffer
		movwf	TxStartPtr	;and place in transmit start pointer
		movwf	TxEndPtr	;and transmit end pointer	
		Bank2
		call	set_test_key	;move constant key by user to key buffer
					;that is overwritten during encryption 
		call 	encrypt		;encrypt RX buffer data
		Bank0
		bcf	Flags,ReceivedCR;clear <CR> received indicator
Copy2:		btfsc	Flags,RxBufEmpty;check if Rx buffer is empty
		return			;if so then return
		call	GetRxBuffer	;get data from receive buffer
		call	PutTxBuffer	;put data in transmit buffer
		goto	Copy2		;if not the same then move another byte
		

;----------------------------------------------------------------------------
;Decrypt receive buffer data and move to transmit buffer 
		
CopyDEC:	Bank0			;select bank 2
		movlw	0xa0		;take address of transmit buffer
		movwf	TxStartPtr	;and place in transmit start pointer
		movwf	TxEndPtr	;and transmit end pointer
		Bank2
		call	set_test_key	;move constant key by user to key buffer
					;that is overwritten during encryption 
		call	init_decryption_key;calculate initial decryption key
		call 	decrypt		;decrypt RX buffer data
		Bank0
		bcf	Flags,ReceivedLF;clear <LF> received indicator
Copy3:		btfsc	Flags,RxBufEmpty;check if Rx buffer is empty
		return			;if so then return
		call	GetRxBuffer	;get data from receive buffer
		call	PutTxBuffer	;put data in transmit buffer
		goto	Copy3		;if not the same then move another byte
		
;----------------------------------------------------------------------------
;Load user input 16 byte key into key test block 

set_test_key:
		movf	KeyBuffer+0x0,W
		movwf	key+0x0
		movf	KeyBuffer+0x1,W
		movwf	key+0x1
		movf	KeyBuffer+0x2,W
		movwf	key+0x2
		movf	KeyBuffer+0x3,W
		movwf	key+0x3
		movf	KeyBuffer+0x4,W
		movwf	key+0x4
		movf	KeyBuffer+0x5,W
		movwf	key+0x5
		movf	KeyBuffer+0x6,W
		movwf	key+0x6
		movf	KeyBuffer+0x7,W
		movwf	key+0x7
		movf	KeyBuffer+0x8,W
		movwf	key+0x8
		movf	KeyBuffer+0x9,W
		movwf	key+0x9
		movf	KeyBuffer+0xA,W
		movwf	key+0xA
		movf	KeyBuffer+0xB,W
		movwf	key+0xB
		movf	KeyBuffer+0xC,W
		movwf	key+0xC
		movf	KeyBuffer+0xD,W
		movwf	key+0xD
		movf	KeyBuffer+0xE,W
		movwf	key+0xE
		movf	KeyBuffer+0xF,W
		movwf	key+0xF
		return


; ********************* KEY_ADDITION ****************************
; This procedure makes: block ^= key ( ^= means block = block XOR key)
; Input: 	None
; Outup: 	
; Globals: 	block, key
; OBS: 		Implemented without a loop to increase speed
; ***************************************************************

key_addition:
	movf	key+0x0,w			; block[0] ^= key[0]; 
	xorwf	block+0x0,f

	movf	key+0x1,w			; block[1] ^= key[1]; 
	xorwf	block+0x1,f

	movf	key+0x2,w			; block[2] ^= key[2]; 
	xorwf	block+0x2,f

	movf	key+0x3,w			; block[3] ^= key[3]; 
	xorwf	block+0x3,f

	movf	key+0x4,w			; block[4] ^= key[4]; 
	xorwf	block+0x4,f

	movf	key+0x5,w			; block[5] ^= key[5]; 
	xorwf	block+0x5,f

	movf	key+0x6,w			; block[6] ^= key[6]; 
	xorwf	block+0x6,f

	movf	key+0x7,w			; block[7] ^= key[7]; 
	xorwf	block+0x7,f

	movf	key+0x8,w			; block[8] ^= key[8]; 
	xorwf	block+0x8,f

	movf	key+0x9,w			; block[9] ^= key[9]; 
	xorwf	block+0x9,f

	movf	key+0x0A,w			; block[10] ^= key[10]; 
	xorwf	block+0x0A,f

	movf	key+0x0B,w			; block[11] ^= key[11]; 
	xorwf	block+0x0B,f

	movf	key+0x0C,w			; block[12] ^= key[12]; 
	xorwf	block+0x0C,f

	movf	key+0x0D,w			; block[13] ^= key[13]; 
	xorwf	block+0x0D,f

	movf	key+0x0E,w			; block[14] ^= key[14]; 
	xorwf	block+0x0E,f

	movf	key+0x0F,w			; block[15] ^= key[15]; 
	xorwf	block+0x0F,f
	return


; *********************** SUBSTITUTION_S **************************
; This procedure makes: block[i] = S_box[block[i]] 
;			
; Input: 	
; Outup: 	
; Globals: aux,block,FSR,PCLATH
; *****************************************************************


substitution_S:				; implements the direct substitution
	movlw	HIGH S_table		; selects segment 
	movwf	PCLATH			; 
					; it works like: for i(0....15)
put_s_table_b0:
	movlw	D'99'			; if (block[i]==0) --> block[i]=99D 
	movf	block+0x0,f
	btfsc	STATUS,Z
	goto	put_b0
	decf	block+0x0,w
	call	S_table			; else block[i] = S_table[block[i]-1]
put_b0:
	movwf	block+0x0

put_s_table_b1:
	movlw	D'99'			; 
	movf	block+0x1,f
	btfsc	STATUS,Z
	goto	put_b1
	decf	block+0x1,w
	call	S_table			; 
put_b1:
	movwf	block+0x1

put_s_table_b2:
	movlw	D'99'			; 
	movf	block+0x2,f
	btfsc	STATUS,Z
	goto	put_b2
	decf	block+0x2,w
	call	S_table			; 
put_b2:
	movwf	block+0x2

put_s_table_b3:
	movlw	D'99'			; 
	movf	block+0x3,f
	btfsc	STATUS,Z
	goto	put_b3
	decf	block+0x3,w
	call	S_table			; 
put_b3:
	movwf	block+0x3

put_s_table_b4:
	movlw	D'99'			; 
	movf	block+0x4,f
	btfsc	STATUS,Z
	goto	put_b4
	decf	block+0x4,w
	call	S_table			; 
put_b4:
	movwf	block+0x4

put_s_table_b5:
	movlw	D'99'			; 
	movf	block+0x5,f
	btfsc	STATUS,Z
	goto	put_b5
	decf	block+0x5,w
	call	S_table			; 
put_b5:
	movwf	block+0x5

put_s_table_b6:
	movlw	D'99'			; 
	movf	block+0x6,f
	btfsc	STATUS,Z
	goto	put_b6
	decf	block+0x6,w
	call	S_table			; 
put_b6:
	movwf	block+0x6

put_s_table_b7:
	movlw	D'99'			; 
	movf	block+0x7,f
	btfsc	STATUS,Z
	goto	put_b7
	decf	block+0x7,w
	call	S_table			; 
put_b7:
	movwf	block+0x7

put_s_table_b8:
	movlw	D'99'			; 
	movf	block+0x8,f
	btfsc	STATUS,Z
	goto	put_b8
	decf	block+0x8,w
	call	S_table			; 
put_b8:
	movwf	block+0x8

put_s_table_b9:
	movlw	D'99'			; 
	movf	block+0x9,f
	btfsc	STATUS,Z
	goto	put_b9
	decf	block+0x9,w
	call	S_table			; 
put_b9:
	movwf	block+0x9

put_s_table_bA:
	movlw	D'99'			; 
	movf	block+0xA,f
	btfsc	STATUS,Z
	goto	put_bA
	decf	block+0xA,w
	call	S_table			; 
put_bA:
	movwf	block+0xA

put_s_table_bB:
	movlw	D'99'			; 
	movf	block+0xB,f
	btfsc	STATUS,Z
	goto	put_bB
	decf	block+0xB,w
	call	S_table			; 
put_bB:
	movwf	block+0xB

put_s_table_bC:
	movlw	D'99'			; 
	movf	block+0xC,f
	btfsc	STATUS,Z
	goto	put_bC
	decf	block+0xC,w
	call	S_table			; 
put_bC:
	movwf	block+0xC

put_s_table_bD:
	movlw	D'99'			; 
	movf	block+0xD,f
	btfsc	STATUS,Z
	goto	put_bD
	decf	block+0xD,w
	call	S_table			; 
put_bD:
	movwf	block+0xD

put_s_table_bE:
	movlw	D'99'			; 
	movf	block+0xE,f
	btfsc	STATUS,Z
	goto	put_bE
	decf	block+0xE,w
	call	S_table			; 
put_bE:
	movwf	block+0xE

put_s_table_bF:
	movlw	D'99'			; 
	movf	block+0xF,f
	btfsc	STATUS,Z
	goto	put_bF
	decf	block+0xF,w
	call	S_table			; 
put_bF:
	movwf	block+0xF
	return

; *********************** SUBSTITUTION_Si *************************
; This procedure makes: block[i] = Si_box[block[i]].
; This is the inverse mapping because:
;
;	b = S_box[a] and
;	a = Si_box[b]
;			
; Input: 	
; Outup: 	
; Globals: aux,block,FSR,PCLATH
; *****************************************************************

substitution_Si: 			; implements the inverse substitution
	movlw	HIGH Si_table		; selects segment 
	movwf	PCLATH			; 
					; it works like: for i(0....15)	
put_si_table_b0:
	movlw	D'82'			; if (block[i]==0) block[]=82D
	movf	block+0x0,f
	btfsc	STATUS,Z
	goto	putsi_b0
	decf	block+0x0,w
	call	Si_table		; else block[i] = Si_table[block[i]-1]
putsi_b0:
	movwf	block+0x0

put_si_table_b1:
	movlw	D'82'			; 
	movf	block+0x1,f
	btfsc	STATUS,Z
	goto	putsi_b1
	decf	block+0x1,w
	call	Si_table		; 
putsi_b1:
	movwf	block+0x1

put_si_table_b2:
	movlw	D'82'			; 
	movf	block+0x2,f
	btfsc	STATUS,Z
	goto	putsi_b2
	decf	block+0x2,w
	call	Si_table		;
putsi_b2:
	movwf	block+0x2

put_si_table_b3:
	movlw	D'82'			;
	movf	block+0x3,f
	btfsc	STATUS,Z
	goto	putsi_b3
	decf	block+0x3,w
	call	Si_table		;
putsi_b3:
	movwf	block+0x3

put_si_table_b4:
	movlw	D'82'			;
	movf	block+0x4,f
	btfsc	STATUS,Z
	goto	putsi_b4
	decf	block+0x4,w
	call	Si_table		;
putsi_b4:
	movwf	block+0x4

put_si_table_b5:
	movlw	D'82'			;
	movf	block+0x5,f
	btfsc	STATUS,Z
	goto	putsi_b5
	decf	block+0x5,w
	call	Si_table		;
putsi_b5:
	movwf	block+0x5

put_si_table_b6:
	movlw	D'82'			;
	movf	block+0x6,f
	btfsc	STATUS,Z
	goto	putsi_b6
	decf	block+0x6,w
	call	Si_table		;
putsi_b6:
	movwf	block+0x6

put_si_table_b7:
	movlw	D'82'			;
	movf	block+0x7,f
	btfsc	STATUS,Z
	goto	putsi_b7
	decf	block+0x7,w
	call	Si_table		;
putsi_b7:
	movwf	block+0x7

put_si_table_b8:
	movlw	D'82'			;
	movf	block+0x8,f
	btfsc	STATUS,Z
	goto	putsi_b8
	decf	block+0x8,w
	call	Si_table		;
putsi_b8:
	movwf	block+0x8

put_si_table_b9:
	movlw	D'82'			;
	movf	block+0x9,f
	btfsc	STATUS,Z
	goto	putsi_b9
	decf	block+0x9,w
	call	Si_table		;
putsi_b9:
	movwf	block+0x9

put_si_table_bA:
	movlw	D'82'			;
	movf	block+0xA,f
	btfsc	STATUS,Z
	goto	putsi_bA
	decf	block+0xA,w
	call	Si_table		;
putsi_bA:
	movwf	block+0xA

put_si_table_bB:
	movlw	D'82'			;
	movf	block+0xB,f
	btfsc	STATUS,Z
	goto	putsi_bB
	decf	block+0xB,w
	call	Si_table		;
putsi_bB:
	movwf	block+0xB

put_si_table_bC:
	movlw	D'82'			;
	movf	block+0xC,f
	btfsc	STATUS,Z
	goto	putsi_bC
	decf	block+0xC,w
	call	Si_table		;
putsi_bC:
	movwf	block+0xC

put_si_table_bD:
	movlw	D'82'			;
	movf	block+0xD,f
	btfsc	STATUS,Z
	goto	putsi_bD
	decf	block+0xD,w
	call	Si_table		;
putsi_bD:
	movwf	block+0xD

put_si_table_bE:
	movlw	D'82'			;
	movf	block+0xE,f
	btfsc	STATUS,Z
	goto	putsi_bE
	decf	block+0xE,w
	call	Si_table		;
putsi_bE:
	movwf	block+0xE

put_si_table_bF:
	movlw	D'82'			;
	movf	block+0xF,f
	btfsc	STATUS,Z
	goto	putsi_bF
	decf	block+0xF,w
	call	Si_table		;
putsi_bF:
	movwf	block+0xF
	return


; *********************** ENC_SHIFT_ROW and DEC_SHIFT_ROW *******************************
; These procedures shift rows (1,2 and 3 but NOT 0) a variable 
; amount on the direction (encryption or decryption)
; Input: 	 
; Outup: 	shifted block
; Globals: 	aux, block, row_vector
; OBS: 
; 	As defined in the AES Proposal: Rijndael document,
;   	this procedure ciclically shifts rows 1,2 and 3 by offsets
;	that for 128 bits blocks and key are defined as:
;	Cipher:		row1 --> 1, row2 -->2 and row3 -->3
;	Decipher:	row1 --> 3, row2 -->2 and row3 -->1.
;
;	It is also equivalent to the folowing reference 
;	C code designed by Paulo Barreto and Vincent Rijmen:
;	** parameter "d" gives the direction: 	0 = cipher
;						1 = decipher 
;	
;	static word8 shifts[3][4][2] = {0, 0,
;					1, 3,
;					2, 2,
;					3, 1,
;
;					0, 0,
;					1, 5,
;					2, 4,
;					3, 3,
;
;					0, 0,
;					1, 7,
;					3, 5,
;					4, 4}; 
;
;	void ShiftRow(word8 a[4][MAXBC], word8 d, word8 BC) 
;	{
;	/* Row 0 remains unchanged * The other three rows are shifted a variable amount*/
;	 word8 tmp[MAXBC];
;	 int i, j;
;
;	 for(i = 1; i < 4; i++) 
;	 {
;	  for(j = 0; j < BC; j++) tmp[j] = a[i][(j + shifts[SC][i][d]) % BC];
;         for(j = 0; j < BC; j++) a[i][j] = tmp[j];
;	 }
;       }
;
;	Obs: BC = 4, SC=0 
;	d=0 -> encription
;	d=1 -> encription
;
; ***************************************************************************************

enc_shift_row:

; Rotates left row 1 one position

	movf	block+0x1,w
	movwf	aux
	movf	block+0x5,w		;
	movwf	block+0x1
	movf	block+0x9,w		;
	movwf	block+0x5
	movf	block+0xD,w		;
	movwf	block+0x9
	movf	aux,w
	movwf	block+0xD		;


; Rotates left row 2 two positions from position block+0x0A
	
	movf	block+0x2,w
	movwf	aux
	movf	block+0x6,w
	movwf	aux1
	
	movf	block+0xA,w
	movwf	block+0x2
	movf	block+0xE,w
	movwf	block+0x6

	movf	aux,w
	movwf	block+0xA
	movf	aux1,w
	movwf	block+0xE

; Rotates left row 3 three positions from block+0xB


	movf	block+0xF,w
	movwf	aux
	movf	block+0xB,w
	movwf	block+0xF
	movf	block+0x7,w
	movwf	block+0xB
	movf	block+0x3,w
	movwf	block+0x7
	movf	aux,w
	movwf	block+0x3
	return	

;****************************************************************************************

dec_shift_row:

; Rotates right row 1 one position 

	movf	block+0xD,w
	movwf	aux
	movf	block+0x9,w
	movwf	block+0xD
	movf	block+0x5,w
	movwf	block+0x9
	movf	block+0x1,w
	movwf	block+0x5
	movf	aux,w
	movwf	block+0x1
	
; Rotates right row 2 two positions 

	movf	block+0xA,w
	movwf	aux
	movf	block+0xE,w
	movwf	aux1
	movf	block+0x2,w
	movwf	block+0xA
	movf	block+0x6,w
	movwf	block+0xE
	movf	aux,w
	movwf	block+0x2
	movf	aux1,w
	movwf	block+0x6

; Rotates right row 3 one positions 

	movf	block+0x3,w
	movwf	aux
	movf	block+0x7,w
	movwf	block+0x3
	movf	block+0xB,w
	movwf	block+0x7
	movf	block+0xF,w
	movwf	block+0xB
	movf	aux,w
	movwf	block+0xF
	return
	
; *********************** INV_MIX_COLUMN ************************
; This procedure calculates the inverse mix column of the state
; (block with partial results); it is equivalent to the 
; multiplication of the block taken in rows of an 4x4 matrix by 
; the following matrix (over GF2)
; 	
;	0xE 0xB 0xD 0x9	
;	0xB 0xD 0x9 0xE	
;	0xD 0x9 0xE 0xB	
;	0x9 0xE 0xB 0xD	
;	
; The equivalent C code designed by Paulo Barreto and Vincent Rijmen:
;
; void InvMixColumn(word8 a[4][MAXBC], word8 BC) 
;  {/* Mix the four bytes of every column in a linear way
;    * This is the opposite operation of Mixcolumn */
;   word8 b[4][MAXBC];
;   int i, j;
;
;   for(j = 0; j < BC; j++)
;    for(i = 0; i < 4; i++);
;      b[i][j] = mul(0xe,a[i][j])
;      		 ^ mul(0xb,a[(i + 1) % 4][j])
;		 ^ mul(0xd,a[(i + 2) % 4][j])
;		 ^ mul(0x9,a[(i + 3) % 4][j]);
;   for(i = 0; i < 4; i++)
;    for(j = 0; j < BC; j++) a[i][j] = b[i][j];
;  }
;
;	Obs: BC=4
;
;	
; Input: 	block
; Outup: 	block
; Globals: 	aux,aux1,aux2,aux3
;
; OBS:This implementation uses the following optimized equivalent 
;     structure: (as seen in Geoffrey Keating's implementation)
;
; 	aux  = block[i+0] ^ block[i+0x1] ^ block[i+0x2] ^ block[i+0x3];
;	aux1 = xtime(block[i+0x0] ^ block[i+0x2]);
;	aux2 = xtime(block[i+1] ^ block[i+0x3]);
;	aux3 = xtime( xtime( aux1 ^ aux2 ) ^ aux;
;	d0   = xtime(block[i+0x0]^block[i+0x1] ^ aux1);
;	d1   = xtime(block[i+0x1] ^ block[i+0x2] ^ aux2);
;	d2   = xtime(block[i+0x2] ^ block[i+0xC] ^ aux1);
;	Block[i+0x0]   ^= d0 ^ aux3;	
;	Block[i+0x1]   ^= d1 ^ aux3;
;	block[i+0x2]   ^= d2 ^ aux3;
;	Block[i+0x3]    = block[i+0x0] ^ block[i+1] ^ block[i+2] ^ aux;
;
; ***************************************************************

	
inv_mix_column:

; **** it begins by calculating inv_mix_column for the FIRST column ****

	movf	block+0x0,w		; aux = block+0x0 ^ block+0x1 ^ block+0x2 ^ block+0x3 		
	xorwf	block+0x1,w	
	xorwf	block+0x2,w
	xorwf	block+0x3,w
	movwf	aux

	movf	block+0x0,w		; aux1 = xtime(block+0x0 ^ block+0x2)
	xorwf	block+0x2,w
	movwf	aux1
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux1,f
	btfsc	STATUS,C
	xorwf	aux1,f
	
	movf	block+0x1,w		; aux2 = xtime(block+0x1 ^ block+0x3)
	xorwf	block+0x3,w		
	movwf	aux2
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux2,f
	btfsc	STATUS,C
	xorwf	aux2,f
	
	movf	aux1,w			; aux3 = xtime(xtime(block+0x1 ^ block+0x2)) ^ aux
	xorwf	aux2,w		
	movwf	aux3
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	movf	aux,w
	xorwf	aux3,f
	
	movf	block+0x0,w		; d0 = xtime(block+0x0 ^ block+0x1 ^ aux1)
	xorwf	block+0x1,w
	xorwf	aux1,w
	movwf	d0
	movlw	0x1B
	bcf	STATUS,C
	rlf	d0,f
	btfsc	STATUS,C
	xorwf	d0,f

	movf	block+0x1,w		; d1 = xtime(block+0x1 ^ block+0x2 ^ aux2)
	xorwf	block+0x2,w
	xorwf	aux2,w
	movwf	d1
	movlw	0x1B
	bcf	STATUS,C
	rlf	d1,f
	btfsc	STATUS,C
	xorwf	d1,f

	
	movf	block+0x2,w		; d2 = xtime(block+0x2 ^ block+0x3 ^ aux1)
	xorwf	block+0x3,w
	xorwf	aux1,w
	movwf	d2
	movlw	0x1B
	bcf	STATUS,C
	rlf	d2,f
	btfsc	STATUS,C
	xorwf	d2,f


	movf	d0,w			; block+0 ^= d0 ^ aux3
	xorwf	aux3,w
	xorwf	block+0x0,f

	movf	d1,w			; block+1 ^= d1 ^ aux3
	xorwf	aux3,w
	xorwf	block+0x1,f
	
	movf	d2,w			; block+2 ^= d2 ^ aux3
	xorwf	aux3,w
	xorwf	block+0x2,f

	movf	block+0x0,w		; block+3 = block+0 ^ block+1 ^ block+2 ^ aux
	xorwf	block+0x1,w
	xorwf	block+0x2,w
	xorwf	aux,w
	movwf	block+0x3
	
; ******* inv_mix_column for the SECOND column *******
; It uses the same structure used in the first column

	movf	block+0x4,w		; 
	xorwf	block+0x5,w	
	xorwf	block+0x6,w
	xorwf	block+0x7,w
	movwf	aux

	movf	block+0x4,w		; 
	xorwf	block+0x6,w
	movwf	aux1
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux1,f
	btfsc	STATUS,C
	xorwf	aux1,f
	
	movf	block+0x5,w		; 
	xorwf	block+0x7,w		
	movwf	aux2
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux2,f
	btfsc	STATUS,C
	xorwf	aux2,f
	
	movf	aux1,w			;
	xorwf	aux2,w		
	movwf	aux3
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	movf	aux,w
	xorwf	aux3,f
	
	movf	block+0x4,w		;
	xorwf	block+0x5,w
	xorwf	aux1,w
	movwf	d0
	movlw	0x1B
	bcf	STATUS,C
	rlf	d0,f
	btfsc	STATUS,C
	xorwf	d0,f

	movf	block+0x5,w		;
	xorwf	block+0x6,w
	xorwf	aux2,w
	movwf	d1
	movlw	0x1B
	bcf	STATUS,C
	rlf	d1,f
	btfsc	STATUS,C
	xorwf	d1,f

	
	movf	block+0x6,w		;
	xorwf	block+0x7,w
	xorwf	aux1,w
	movwf	d2
	movlw	0x1B
	bcf	STATUS,C
	rlf	d2,f
	btfsc	STATUS,C
	xorwf	d2,f


	movf	d0,w			;
	xorwf	aux3,w
	xorwf	block+0x4,f

	movf	d1,w			;
	xorwf	aux3,w
	xorwf	block+0x5,f
	
	movf	d2,w			;
	xorwf	aux3,w
	xorwf	block+0x6,f

	movf	block+0x4,w		;
	xorwf	block+0x5,w
	xorwf	block+0x6,w
	xorwf	aux,w
	movwf	block+0x7


; ******* inv_mix_column for the THIRD column *******
; It uses the same structure used in the first column

	movf	block+0x8,w	
	xorwf	block+0x9,w	
	xorwf	block+0xA,w
	xorwf	block+0xB,w
	movwf	aux

	movf	block+0x8,w		; 
	xorwf	block+0xA,w
	movwf	aux1
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux1,f
	btfsc	STATUS,C
	xorwf	aux1,f
	
	movf	block+0x9,w		; 
	xorwf	block+0xB,w		
	movwf	aux2
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux2,f
	btfsc	STATUS,C
	xorwf	aux2,f
	
	movf	aux1,w			;
	xorwf	aux2,w		
	movwf	aux3
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	movf	aux,w
	xorwf	aux3,f
	
	movf	block+0x8,w		;
	xorwf	block+0x9,w
	xorwf	aux1,w
	movwf	d0
	movlw	0x1B
	bcf	STATUS,C
	rlf	d0,f
	btfsc	STATUS,C
	xorwf	d0,f

	movf	block+0x9,w		;
	xorwf	block+0xA,w
	xorwf	aux2,w
	movwf	d1
	movlw	0x1B
	bcf	STATUS,C
	rlf	d1,f
	btfsc	STATUS,C
	xorwf	d1,f

	
	movf	block+0xA,w		;
	xorwf	block+0xB,w
	xorwf	aux1,w
	movwf	d2
	movlw	0x1B
	bcf	STATUS,C
	rlf	d2,f
	btfsc	STATUS,C
	xorwf	d2,f


	movf	d0,w			;
	xorwf	aux3,w
	xorwf	block+0x8,f

	movf	d1,w			;
	xorwf	aux3,w
	xorwf	block+0x9,f
	
	movf	d2,w			;
	xorwf	aux3,w
	xorwf	block+0xA,f

	movf	block+0x8,w		;
	xorwf	block+0x9,w
	xorwf	block+0xA,w
	xorwf	aux,w
	movwf	block+0xB

; ******* inv_mix_column for the LAST (FOURTH) column *******
; It uses the same structure used in the first column


	movf	block+0xC,w		; 
	xorwf	block+0xD,w	
	xorwf	block+0xE,w
	xorwf	block+0xF,w
	movwf	aux

	movf	block+0xC,w		;
	xorwf	block+0xE,w
	movwf	aux1
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux1,f
	btfsc	STATUS,C
	xorwf	aux1,f
	
	movf	block+0xD,w		;
	xorwf	block+0xF,w		
	movwf	aux2
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux2,f
	btfsc	STATUS,C
	xorwf	aux2,f
	
	movf	aux1,w			;
	xorwf	aux2,w		
	movwf	aux3
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	movf	aux,w
	xorwf	aux3,f
	
	movf	block+0xC,w		;
	xorwf	block+0xD,w
	xorwf	aux1,w
	movwf	d0
	movlw	0x1B
	bcf	STATUS,C
	rlf	d0,f
	btfsc	STATUS,C
	xorwf	d0,f

	movf	block+0xD,w		;
	xorwf	block+0xE,w
	xorwf	aux2,w
	movwf	d1
	movlw	0x1B
	bcf	STATUS,C
	rlf	d1,f
	btfsc	STATUS,C
	xorwf	d1,f

	
	movf	block+0xE,w		;
	xorwf	block+0xF,w
	xorwf	aux1,w
	movwf	d2
	movlw	0x1B
	bcf	STATUS,C
	rlf	d2,f
	btfsc	STATUS,C
	xorwf	d2,f


	movf	d0,w			;
	xorwf	aux3,w
	xorwf	block+0xC,f

	movf	d1,w			;
	xorwf	aux3,w
	xorwf	block+0xD,f
	
	movf	d2,w			;
	xorwf	aux3,w
	xorwf	block+0xE,f

	movf	block+0xC,w		;
	xorwf	block+0xD,w
	xorwf	block+0xE,w
	xorwf	aux,w
	movwf	block+0xF
	return

; ************************* MIX_COLUMN ************************
; This procedure calculates the direct mix column of the state
; (block with partial results); it is equivalent to the 
; multiplication of the block taken in rows of an 4x4 matrix by 
; the following matrix (over GF2)
; 	
;	0x2 0x3 0x1 0x1	
;	0x3 0x1 0x1 0x2	
;	0x1 0x1 0x2 0x3	
;	0x1 0x2 0x3 0x1	
;	
; The equivalent C code designed by Paulo Barreto and Vincent Rijmen:
;
;	Obs: BC=4
;
;	oid MixColumn(word8 a[4][MAXBC], word8 BC) 
;	{/* Mix the four bytes of every column in a linear way*/
;	 word8 b[4][MAXBC];
;	 int i, j;
;
;	 for(j = 0; j < BC; j++)
;	  for(i = 0; i < 4; i++)
;          b[i][j] = 	mul(2,a[i][j])
;			^ mul(3,a[(i + 1) % 4][j])
;			^ a[(i + 2) % 4][j]
;			^ a[(i + 3) % 4][j];
;  	 for(i = 0; i < 4; i++)
;	  for(j = 0; j < BC; j++) a[i][j] = b[i][j];
;       }
;
;	Obs: BC=4
;
;
; Input: 	
; Outup: 	
; Globals: 	
; ***************************************************************
	
mix_column:

; begins with the mix of column 0

	movf	block+0x0,w		
	xorwf	block+0x1,w
	movwf	aux1			; aux1 = block+0x0 ^ block+0x1 
	xorwf	block+0x2,w
	xorwf	block+0x3,w
	movwf	aux			; aux = block+0x0 ^ block+0x1 ^ block+0x2 ^ block+0x3
	
	movf	block+0x1,w		; aux2 = block+0x1 ^ block+0x2 
	xorwf	block+0x2,w
	movwf	aux2

	movf	block+0x2,w		; aux3 = block+0x2 ^ block+0x3 
	xorwf	block+0x3,w
	movwf	aux3

	call	calc_xtimes		; aux = xtime(aux), aux1 = xtime(aux1), aux2 = xtime(aux2), aux3 = xtime(aux3)

	movf	aux,w			; block+0x0 ^= aux ^ aux1
	xorwf	aux1,w
	xorwf	block+0x0,f

	movf	aux,w			; block+0x1 ^= aux ^ aux2
	xorwf	aux2,w
	xorwf	block+0x1,f

	movf	aux,w			; block+0x2 ^= aux ^ aux3
	xorwf	aux3,w
	xorwf	block+0x2,f

	movf	block+0x0,w		; block+0x3 = block+0x1 ^ block+0x2 ^ block+0x2 ^ aux
	xorwf	block+0x1,w
	xorwf	block+0x2,w
	xorwf	aux,w
	movwf	block+0x3


; mix of column 1

	movf	block+0x4,w
	xorwf	block+0x5,w
	movwf	aux1			;
	xorwf	block+0x6,w
	xorwf	block+0x7,w
	movwf	aux
	
	movf	block+0x5,w
	xorwf	block+0x6,w
	movwf	aux2

	movf	block+0x6,w
	xorwf	block+0x7,w
	movwf	aux3

	call	calc_xtimes

	movf	aux,w
	xorwf	aux1,w
	xorwf	block+0x4,f

	movf	aux,w
	xorwf	aux2,w
	xorwf	block+0x5,f

	movf	aux,w
	xorwf	aux3,w
	xorwf	block+0x6,f

	movf	block+0x4,w
	xorwf	block+0x5,w
	xorwf	block+0x6,w
	xorwf	aux,w
	movwf	block+0x7

; mix of column 2

	movf	block+0x8,w
	xorwf	block+0x9,w
	movwf	aux1			; 
	xorwf	block+0xA,w
	xorwf	block+0xB,w
	movwf	aux
	
	movf	block+0x9,w
	xorwf	block+0xA,w
	movwf	aux2

	movf	block+0xA,w
	xorwf	block+0xB,w
	movwf	aux3

	call	calc_xtimes

	movf	aux,w
	xorwf	aux1,w
	xorwf	block+0x8,f

	movf	aux,w
	xorwf	aux2,w
	xorwf	block+0x9,f

	movf	aux,w
	xorwf	aux3,w
	xorwf	block+0xA,f

	movf	block+0x8,w
	xorwf	block+0x9,w
	xorwf	block+0xA,w
	xorwf	aux,w
	movwf	block+0xB


; mix of column 3

	movf	block+0xC,w
	xorwf	block+0xD,w
	movwf	aux1			;
	xorwf	block+0xE,w
	xorwf	block+0xF,w
	movwf	aux
	
	movf	block+0xD,w
	xorwf	block+0xE,w
	movwf	aux2

	movf	block+0xE,w
	xorwf	block+0xF,w
	movwf	aux3

	call	calc_xtimes

	movf	aux,w
	xorwf	aux1,w
	xorwf	block+0xC,f

	movf	aux,w
	xorwf	aux2,w
	xorwf	block+0xD,f

	movf	aux,w
	xorwf	aux3,w
	xorwf	block+0xE,f

	movf	block+0xC,w
	xorwf	block+0xD,w
	xorwf	block+0xE,w
	xorwf	aux,w
	movwf	block+0xF

	return


calc_xtimes:
	movlw	0x1B
	bcf	STATUS,C
	rlf	aux1,f
	btfsc	STATUS,C
	xorwf	aux1,f
	bcf	STATUS,C
	rlf	aux2,f
	btfsc	STATUS,C
	xorwf	aux2,f
	bcf	STATUS,C
	rlf	aux3,f
	btfsc	STATUS,C
	xorwf	aux3,f
	return

; ********************* ENC_KEY_SCHEDULE **********************
; This procedure takes the actual key and generates a new one.
; The equivalent C code fragment as designed by Paulo Barreto 
; and Vincent Rijmen: (key taken as a 4x4 matrix)
;
; 	word32 rcon[30] =      {0x01,0x02, 0x04, 0x08, 
;				0x10, 0x20, 0x40, 0x80, 
;				0x1b, 0x36, 0x6c, 0xd8, 
;				0xab, 0x4d, 0x9a, 0x2f, 
;				0x5e, 0xbc, 0x63, 0xc6, 
;				0x97, 0x35, 0x6a, 0xd4, 
;				0xb3, 0x7d, 0xfa, 0xef, 
;				0xc5, 0x91, };
;
;
;	rconpointer=0;
; 	for(i = 0; i < 4; i++)
; 	 key[i][0] ^= S[key[(i+1)%4][KC-1]];
;	key[0][0] ^= rcon[rconpointer++];
;       for(j = 1; j < KC; j++)
;	 for(i = 0; i < 4; i++) 
;	  key[i][j] ^= key[i][j-1];
;
;	
; Input: 	key
; Outup: 	
; Globals: 	aux,rcon
; ***************************************************************

enc_key_schedule:

	call	calc_s_table_based_values
	movf	rcon,w				; key[0] ^= rcon
	xorwf	key,f
	bcf	STATUS,C
	rlf	rcon,f				; rcon = xtime(rcon)
	btfss	STATUS,C
	goto	complete_round
	movlw	0x1B
	movwf	rcon
complete_round:
	movf	key+0x0,w		; This is equivalent to the 
	xorwf	key+0x4,f		; XOR of each column with the
					; previous one
	movf	key+0x1,w
	xorwf	key+0x5,f
					; first column1 ^= column0
	movf	key+0x2,w
	xorwf	key+0x6,f

	movf	key+0x3,w
	xorwf	key+0x7,f
					; column2 ^= column1
	movf	key+0x4,w
	xorwf	key+0x8,f

	movf	key+0x5,w
	xorwf	key+0x9,f

	movf	key+0x6,w
	xorwf	key+0xA,f

	movf	key+0x7,w
	xorwf	key+0xB,f
					; column3 ^= column2
	movf	key+0x8,w
	xorwf	key+0xC,f

	movf	key+0x9,w
	xorwf	key+0xD,f

	movf	key+0xA,w
	xorwf	key+0xE,f

	movf	key+0xB,w
	xorwf	key+0xF,f
	return


calc_s_table_based_values:

	movlw	HIGH S_table		; set the table segment
	movwf	PCLATH

	movf	key+0xD,w			
	btfss	STATUS,Z
	goto	put_S_table_0xD
	movlw	D'99'
	xorwf	key+0x0,f
	goto	read_key_0xE

put_S_table_0xD:
	decf	key+0xD,w		; key[0x0] ^= s_box[key[0xD]]
	call	S_table
	xorwf	key+0x0,f

read_key_0xE:

	movf	key+0xE,w			
	btfss	STATUS,Z
	goto	put_S_table_0xE
	movlw	D'99'
	xorwf	key+0x1,f
	goto	read_key_0xF

put_S_table_0xE:
	decf	key+0xE,w		; key[0x1] ^= s_box[key[0xE]]	
	call	S_table
	xorwf	key+0x1,f

read_key_0xF:

	movf	key+0xF,w			
	btfss	STATUS,Z
	goto	put_S_table_0xF
	movlw	D'99'
	xorwf	key+0x2,f
	goto	read_key_0xC

put_S_table_0xF:
	decf	key+0xF,w		; key[0x2] ^= s_box[key[0xF]]	
	call	S_table
	xorwf	key+0x2,f

read_key_0xC:

	movf	key+0xC,w			
	btfss	STATUS,Z
	goto	put_S_table_0xC
	movlw	D'99'
	xorwf	key+0x3,f
	return				;

put_S_table_0xC:
	decf	key+0xC,w		; key[0x3] ^= s_box[key[0xC]]	
	call	S_table
	xorwf	key+0x3,f
	return


; *********************** DEC_KEY_SCHEDULE **********************
; This procedure takes the actual key and generates a new one in
; the exact inverse sequence used by enc_key_schedule function
; 
;	
; Input: 	key
; Outup: 	
; Globals: 	aux,rcon
; ***************************************************************

dec_key_schedule:

;  
;first column3 ^= column2

	movf	key+0x8,w	
	xorwf	key+0xC,f

	movf	key+0x09,w	
	xorwf	key+0x0D,f

	movf	key+0x0A,w	
	xorwf	key+0x0E,f

	movf	key+0x0B,w	
	xorwf	key+0x0F,f

;column2 ^= column1

	movf	key+0x04,w	
	xorwf	key+0x08,f

	movf	key+0x05,w	
	xorwf	key+0x09,f

	movf	key+0x06,w	
	xorwf	key+0x0A,f

	movf	key+0x07,w	
	xorwf	key+0x0B,f

;first column1 ^= column0

	movf	key+0x00,w	
	xorwf	key+0x04,f

	movf	key+0x01,w	
	xorwf	key+0x05,f

	movf	key+0x02,w	
	xorwf	key+0x06,f

	movf	key+0x03,w	
	xorwf	key+0x07,f

	movf	rcon,w			; key[ox0] ^= rcon,  rcon>>=1, if carry rcon = 0x80
	xorwf	key,f			
	bcf	STATUS,C		; this is equivalent to the
	rrf	rcon,f			; read of rcon table

	btfss	STATUS,C		; 
	goto	complete_decrypt_round
	movlw	0x80
	movwf	rcon
complete_decrypt_round:
	goto	calc_s_table_based_values		


; ************************** DECRYPT ******************************
; This procedure decipher the plain text in block using key
; Inputs: 	The encrypted text in block[], 
;		The decipher_key in key[]; this key is NOT the 
;		original cipher key used to cipher the plain text, 
;		but the scheduled original.
; Outups: 	The plain text in block 
;		The original cipher key	in key[]
; OBS: 		This implementation follows as possible the original
;		structure and function names used by the reference
;		implementation of AES
; *****************************************************************

decrypt:
	movlw	0x36
	movwf	rcon			; RCON initialization
	call	key_addition		; initial key addition
	movlw	ROUNDS
	movwf	round_counter		;
	goto	dec_first_round
loop_decrypt:
	call	inv_mix_column
dec_first_round:
 	call	substitution_Si		; 
 	call	dec_shift_row
	call	dec_key_schedule
	call	key_addition		; 
	decfsz	round_counter,f
	goto	loop_decrypt
	return
	
; ************************** ENCRYPT ******************************
; This procedure cipher the plain text in block using key
; Inputs: 	The plain_text in block[]
;		The cipher_key in key[]
; Outups: 	The ciphered text in block
;		The rounded (decipher) key in key[]
; OBS: 		This implementation follows as possible the original
;		structure and function names used by the reference
;		implementation of AES
; *****************************************************************

encrypt:
	movlw	0x01
	movwf	rcon			; RCON initialization
	call	key_addition		; initial key addition
	movlw	ROUNDS			; start the round counter for the loop
	movwf	round_counter
loop_encrypt:
	call	substitution_S		; 
	call	enc_shift_row
	decf	round_counter,w
	btfsc	STATUS,Z
	goto	last_round
	call	mix_column
last_round:
	call	enc_key_schedule
	call	key_addition		; key addition
	decfsz	round_counter,f
	goto	loop_encrypt
	return
	

; ***************** INIT_DECRYPTION_KEY ***************************
; This procedure creates the initial deciphering key from the initial 
; cyphering key by multiple application of enc_key_schedule
; Inputs: 	The plain_text in block[]
;		The cipher_key in key[]
; Outups: 	The ciphered text in block
;		The rounded (decipher) key in key[]
; OBS: 		This implementation follows as possible the original
;		structure and function names used by the reference
;		implementation of AES
; *****************************************************************


init_decryption_key:
	movlw	0x01
	movwf	rcon
	movlw	0xA
	movwf	round_counter
loop_init_decryption_key:
	call	enc_key_schedule
	decfsz	round_counter,f
	goto	loop_init_decryption_key
	return

;0E DD 33 D3 C6 21 E5 46 45 5B D8 BA 14 18 BE C8
			
	ORG	0x0600		;Program Memory starting address

S_table:
	addwf	 PCL,f
;	retlw    D'99'		;except S_table[0]
	retlw	 D'124'
	retlw    D'119'		   
	retlw    D'123'
	retlw    D'242'
	retlw    D'107'
	retlw    D'111'
	retlw    D'197'
	retlw    D'48'
	retlw    D'1'
	retlw    D'103'
	retlw    D'43'
	retlw    D'254'
	retlw    D'215'
	retlw    D'171'
	retlw    D'118'
	retlw    D'202'
	retlw    D'130'
	retlw    D'201'
	retlw    D'125'
	retlw    D'250'
	retlw    D'89'
	retlw    D'71'
	retlw    D'240'
	retlw    D'173'
	retlw    D'212'
	retlw    D'162'
	retlw    D'175'
	retlw    D'156'
	retlw    D'164'
	retlw    D'114'
	retlw    D'192'
	retlw    D'183'
	retlw    D'253'
	retlw    D'147'
	retlw    D'38'
	retlw    D'54'
	retlw    D'63'
	retlw    D'247'
	retlw    D'204'
	retlw    D'52'
	retlw    D'165'
	retlw    D'229'
	retlw    D'241'
	retlw    D'113'
	retlw    D'216'	
	retlw    D'49'
	retlw    D'21'
	retlw    D'4'
	retlw    D'199'
	retlw    D'35'
	retlw    D'195'
	retlw    D'24'
	retlw    D'150'	
	retlw    D'5'
	retlw    D'154'
	retlw    D'7'
	retlw    D'18'
	retlw    D'128'
	retlw    D'226'
	retlw    D'235'
	retlw    D'39'
	retlw    D'178'
	retlw    D'117'
	retlw    D'9'
	retlw    D'131'
	retlw    D'44'	
	retlw    D'26'
	retlw    D'27'
	retlw    D'110'
	retlw    D'90'
	retlw    D'160'
	retlw    D'82'
	retlw    D'59'
	retlw    D'214'
	retlw    D'179'
	retlw    D'41'
	retlw    D'227'	
	retlw    D'47'
	retlw    D'132'
	retlw    D'83'
	retlw    D'209'
	retlw    D'0'
	retlw    D'237'
	retlw    D'32'
	retlw    D'252'
	retlw    D'177'
	retlw    D'91'
	retlw    D'106'
	retlw    D'203'
	retlw    D'190'
	retlw    D'57'
	retlw    D'74'
	retlw    D'76'	
	retlw    D'88'
	retlw    D'207'
	retlw    D'208'
	retlw    D'239'
	retlw    D'170'
	retlw    D'251'
	retlw    D'67'
	retlw    D'77'
	retlw    D'51'
	retlw    D'133'
	retlw    D'69'
	retlw    D'249'
	retlw    D'2'
	retlw    D'127'
	retlw    D'80'
	retlw    D'60'
	retlw    D'159'
	retlw    D'168'
	retlw    D'81'
	retlw    D'163'
	retlw    D'64'
	retlw    D'143'
	retlw    D'146'
	retlw    D'157'
	retlw    D'56'
	retlw    D'245'
	retlw    D'188'
	retlw    D'182'
	retlw    D'218'
	retlw    D'33'
	retlw    D'16'
	retlw    D'255'
	retlw    D'243'
	retlw    D'210'
	retlw    D'205'
	retlw    D'12'
	retlw    D'19'
	retlw    D'236'
	retlw    D'95'
	retlw    D'151'
	retlw    D'68'
	retlw    D'23'
	retlw    D'196'
	retlw    D'167'
	retlw    D'126'
	retlw    D'61'
	retlw    D'100'
	retlw    D'93'
	retlw    D'25'
	retlw    D'115'
	retlw    D'96'
	retlw    D'129'
	retlw    D'79'
	retlw    D'220'
	retlw    D'34'
	retlw    D'42'
	retlw    D'144'
	retlw    D'136'
	retlw    D'70'
	retlw    D'238'
	retlw    D'184'
	retlw    D'20'
	retlw    D'222'
	retlw    D'94'
	retlw    D'11'
	retlw    D'219'
	retlw    D'224'
	retlw    D'50'
	retlw    D'58'
	retlw    D'10'
	retlw    D'73'
	retlw    D'6'
	retlw    D'36'
	retlw    D'92'
	retlw    D'194'
	retlw    D'211'
	retlw    D'172'
	retlw    D'98'
	retlw    D'145'
	retlw    D'149'
	retlw    D'228'
	retlw    D'121'
	retlw    D'231'
	retlw    D'200'
	retlw    D'55'
	retlw    D'109'
	retlw    D'141'
	retlw    D'213'
	retlw    D'78'
	retlw    D'169'
	retlw    D'108'
	retlw    D'86'
	retlw    D'244'
	retlw    D'234'
	retlw    D'101'
	retlw    D'122'
	retlw    D'174'
	retlw    D'8'
	retlw    D'186'
	retlw    D'120'
	retlw    D'37'
	retlw    D'46'
	retlw    D'28'
	retlw    D'166'
	retlw    D'180'
	retlw    D'198'
	retlw    D'232'
	retlw    D'221'
	retlw    D'116'
	retlw    D'31'
	retlw    D'75'
	retlw    D'189'
	retlw    D'139'
	retlw    D'138'
	retlw    D'112'
	retlw    D'62'
	retlw    D'181'
	retlw    D'102'
	retlw    D'72'
	retlw    D'3'
	retlw    D'246'
	retlw    D'14'
	retlw    D'97'
	retlw    D'53'
	retlw    D'87'
	retlw    D'185'
	retlw    D'134'
	retlw    D'193'
	retlw    D'29'
	retlw    D'158'
	retlw    D'225'
	retlw    D'248'
	retlw    D'152'
	retlw    D'17'
	retlw    D'105'
	retlw    D'217'
	retlw    D'142'
	retlw    D'148'
	retlw    D'155'
	retlw    D'30'
	retlw    D'135'
	retlw    D'233'
	retlw    D'206'
	retlw    D'85'
	retlw    D'40'
	retlw    D'223'
	retlw    D'140'
	retlw    D'161'
	retlw    D'137'
	retlw    D'13'
	retlw    D'191'
	retlw    D'230'
	retlw    D'66'
	retlw    D'104'
	retlw    D'65'
	retlw    D'153'
	retlw    D'45'
	retlw    D'15'
	retlw    D'176'
	retlw    D'84'
	retlw    D'187'
	retlw    D'22'

	ORG	0x0700		;Program Memory starting address

Si_table:
	addwf	 PCL,f
;	retlw    D'82'		;except Si_table[0]
	retlw    D'9'
	retlw    D'106'
	retlw    D'213'
	retlw    D'48'
	retlw    D'54'
	retlw    D'165'
	retlw    D'56'
	retlw    D'191'
	retlw    D'64'
	retlw    D'163'
	retlw    D'158'
	retlw    D'129'
	retlw    D'243'
	retlw    D'215'
	retlw    D'251'
	retlw    D'124'
	retlw    D'227'
	retlw    D'57'
	retlw    D'130'
	retlw    D'155'
	retlw    D'47'
	retlw    D'255'
	retlw    D'135'
	retlw    D'52'
	retlw    D'142'
	retlw    D'67'
	retlw    D'68'
	retlw    D'196'
	retlw    D'222'
	retlw    D'233'
	retlw    D'203'
	retlw    D'84'
	retlw    D'123'
	retlw    D'148'
	retlw    D'50'
	retlw    D'166'
	retlw    D'194'
	retlw    D'35'
	retlw    D'61'
	retlw    D'238'
	retlw    D'76'
	retlw    D'149'
	retlw    D'11'
	retlw    D'66'
	retlw    D'250'
	retlw    D'195'
	retlw    D'78'
	retlw    D'8'
	retlw    D'46'
	retlw    D'161'
	retlw    D'102'
	retlw    D'40'
	retlw    D'217'
	retlw    D'36'
	retlw    D'178'
	retlw    D'118'
	retlw    D'91'
	retlw    D'162'
	retlw    D'73'
	retlw    D'109'
	retlw    D'139'
	retlw    D'209'
	retlw    D'37'
	retlw    D'114'
	retlw    D'248'
	retlw    D'246'
	retlw    D'100'
	retlw    D'134'
	retlw    D'104'
	retlw    D'152'
	retlw    D'22'
	retlw    D'212'
	retlw    D'164'
	retlw    D'92'
	retlw    D'204'
	retlw    D'93'
	retlw    D'101'
	retlw    D'182'
	retlw    D'146'
	retlw    D'108'
	retlw    D'112'
	retlw    D'72'
	retlw    D'80'
	retlw    D'253'
	retlw    D'237'
	retlw    D'185'
	retlw    D'218'
	retlw    D'94'
	retlw    D'21'
	retlw    D'70'
	retlw    D'87'
	retlw    D'167'
	retlw    D'141'
	retlw    D'157'
	retlw    D'132'
	retlw    D'144'
	retlw    D'216'
	retlw    D'171'
	retlw    D'0'
	retlw    D'140'
	retlw    D'188'
	retlw    D'211'
	retlw    D'10'
	retlw    D'247'
	retlw    D'228'
	retlw    D'88'
	retlw    D'5'
	retlw    D'184'
	retlw    D'179'
	retlw    D'69'
	retlw    D'6'
	retlw    D'208'
	retlw    D'44'
	retlw    D'30'
	retlw    D'143'
	retlw    D'202'
	retlw    D'63'
	retlw    D'15'
	retlw    D'2'
	retlw    D'193'
	retlw    D'175'
	retlw    D'189'
	retlw    D'3'
	retlw    D'1'
	retlw    D'19'
	retlw    D'138'
	retlw    D'107'
	retlw    D'58'
	retlw    D'145'
	retlw    D'17'
	retlw    D'65'
	retlw    D'79'
	retlw    D'103'
	retlw    D'220'
	retlw   

[size=9:57c4fb864a][color=#999
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top