// CRC.java
// Maria Kazandjieva, marykaz@hotmail.com, Summer 2003

// This file puts together a byte array over which CRC has to be calculated
// Right now the CRC function is not working
// In theaory, when correct CRC is calculated, it should be appended to the
	// end of the byte array and the resulting will be a valid comman for the RFID reader

import java.io.*;
import java.util.*;
import java.lang.String;
import java.math.BigInteger;

public class CRC {

	public CRC() {}

	public static void main(String [] args){



		short crc_value = 0;
		int tagType = 01;
		String[] tagstr;
		int[] tagID = new int[8];
		byte[] data = new byte[4];
		byte[] tag = new byte[8];
		byte[] startB = new byte[1];
		byte[] numB = new byte[1];

		// ** STX byte
		byte[] stxB = new BigInteger("2", 16).toByteArray();
		System.out.println("****STX: " + stxB[0]);

		// ** TagType 01
		byte[] tagTypeB = new BigInteger("1", 16).toByteArray();
		System.out.println("****TagType: " + tagTypeB[0]);


		// ** set the appropriate flags and construct the FLAGS byte
		String[] flags = {"RID_F", "TID_F", "CRC_F", "AFI_F", "RF_F", "LOCK_F",
							"INV_F", "LOOP_F"};
	    BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
	    String s1 = "";
	    String[] flag = new String[8];
	    String flagString = "";

		System.out.println("\n\nStep 1: Constructing the FLAGS byte. Enter 1 or 0 for each flag.");

		for (int i=0; i<flags.length; i++){
			System.out.print(flags[i] + ": ");
			try {
                    s1 = buffer.readLine();
                    flag[i] = s1;
                    flagString = flagString.concat(s1);

                } catch (IOException ioe){System.out.println("Did not read in");};
		}

		System.out.println("flagString = " + flagString);
		int a = Integer.parseInt(flagString, 2);

		System.out.println("a = " + a);
		flagString = Integer.toHexString(a);
		System.out.println("flagString = " + flagString);

		byte[] flagValue = new byte[4];
		int val = Integer.parseInt( flagString, 16 );
		flagValue[0] = (byte) ( ( val >>> 24 ) & 0xff );
		flagValue[1] = (byte) ( ( val >>> 16 ) & 0xff );
		flagValue[2] = (byte) ( ( val >>> 8 ) & 0xff );
		flagValue[3] = (byte) ( ( val >>> 0 ) & 0xff ); // this is the one we need

		System.out.println("flagValue = " + flagValue[2] + " and " + flagValue[3]);

		// ** end of constructing the FLAGS byte

		byte [] testByte = {(byte)0x02, (byte)0x60, (byte)0x44,
							(byte)0x01,  (byte)0xE0, (byte)0x04,
							(byte)0x01, (byte)0x00, (byte)0x01, (byte)0xD6, (byte)0xF8,
							(byte)0x6A, (byte)0x00, (byte)0x01, (byte)0x13, (byte)0x37,
							(byte)0x13, (byte)0x37};




		printBytes(testByte);
		CRCcalc(testByte);



		// ** ask the user for the command and made it into a byte
		// ** options are READ=24, WRITE=44, and SELECT=14
		String commandstr ="";
		int intcommand = 0;

		System.out.println("Step 2: The command. Enter one of: select (14); write (44); read (24)" );
		try {
		     commandstr = buffer.readLine();
		     intcommand = Integer.parseInt(commandstr);
        	} catch (IOException ioe){
				System.out.println("Did not read in");
			};

 		byte[] command = new BigInteger(commandstr, 16).toByteArray();
 		System.out.println("command = " + command[0]);

		// ** Get the tagID

		if (flag[1].equals("1")){

		String s3 = "";
		System.out.println("Step 3: Enter TagID: ");
		try{
			s3 = buffer.readLine();
		}catch (IOException ioe){System.out.println("Did not read in");}

		System.out.println("s3 = " + s3);

		//divide the TID string into 8 separate strings
		tagstr = new String[8];
		tagstr[0] = s3.substring(0,2);
		tagstr[1] = s3.substring(2,4);
		tagstr[2] = s3.substring(4,6);
		tagstr[3] = s3.substring(6,8);
		tagstr[4] = s3.substring(8,10);
		tagstr[5] = s3.substring(10,12);
		tagstr[6] = s3.substring(12,14);
		tagstr[7] = s3.substring(14,16);

		tagID[0] = Integer.parseInt(tagstr[0], 16);
		tagID[1] = Integer.parseInt(tagstr[1], 16);
		tagID[2] = Integer.parseInt(tagstr[2], 16);
		tagID[3] = Integer.parseInt(tagstr[3], 16);
		tagID[4] = Integer.parseInt(tagstr[4], 16);
		tagID[5] = Integer.parseInt(tagstr[5], 16);
		tagID[6] = Integer.parseInt(tagstr[6], 16);
		tagID[7] = Integer.parseInt(tagstr[7], 16);


		tag[7] = (byte) ( ( tagID[7] >>> 0) & 0xff );
		tag[6] = (byte) ( ( tagID[6] >>> 0 ) & 0xff );
		tag[5] = (byte) ( ( tagID[5] >>> 0 ) & 0xff );
		tag[4] = (byte) ( ( tagID[4] >>> 0 ) & 0xff );
		tag[3] = (byte) ( ( tagID[3] >>> 0 ) & 0xff );
		tag[2] = (byte) ( ( tagID[2] >>> 0 ) & 0xff );
		tag[1] = (byte) ( ( tagID[1] >>> 0 ) & 0xff );
		tag[0] = (byte) ( ( tagID[0] >>> 0 ) & 0xff );



		System.out.println("TagID: " + tag[0] + tag[1] + tag[2] +tag[3] + tag[4] + tag[5]
										+ tag[6] + tag[7]);
	}

		// ** ask for STARTING BLOCK if command was READ or WRITE

		if (intcommand==44 || intcommand==24){

		System.out.println("Enter STARTING BLOCK");
		String startBlock = "";
		try{
			startBlock = buffer.readLine();
		}catch (IOException ioe){System.out.println("Did not read in");}
		startB = new BigInteger(startBlock, 16).toByteArray();
		System.out.println("startB = " + startB[0]);
		// ** done getting the starting block


		// ** ask for NUMBER OF BLOCKS if command was READ OR WRITE
		System.out.println ("Enter NUMBER OF BLOCKS");
		String numBlocks = "";
		try{
			numBlocks = buffer.readLine();
		}catch (IOException ioe){System.out.println("Did not read in");}

			numB = new BigInteger(numBlocks, 16).toByteArray();
		System.out.println("numB = " + numB[0]);
		// ** done getting the number of blocks

		// ** enter DATA if command was WRITE
		if (intcommand==44){

		System.out.println("Enter DATA - 4 bytes only");
		String s4 = "";
		try{
			s4 = buffer.readLine();
		}catch (IOException ioe){System.out.println("Did not read in");}

		System.out.println("DATA = " + s4);

		String[] datastr = new String[4];
		int[] dataint = new int[4];
		data = new byte[4];
		int k = 0;
		for (int j=0; j<4; j++){
			datastr[j] = s4.substring(k,k+2);
			dataint[j]= Integer.parseInt(datastr[j], 16);
			data[j] = (byte) ( ( dataint[j] >>> 0) & 0xff );
			k=k+2;
		}

		System.out.println("DATA = " + data[0] + data[1] + data[2] + data[3]);
		// ** got DATA
	}
	}	//end of IFs


	// ** calculate the msg length
	int msgLen = 3; // initial length, includes flag, command, and tag type bytes
	if (flag[1].equals("1")){
		msgLen+=8;
	}
	if (intcommand==24){
		msgLen+=2;
	}
	if (intcommand==44){
		msgLen = msgLen + 2 + 4;
	}

	msgLen+=2; // for the 2 CRC bytes
	String length = Integer.toString(msgLen);

	System.out.println("Total msg lenght is: " + msgLen);
	int[] lenint = new int[1];
	lenint[0]= Integer.parseInt(length, 16);
	byte[] len = new byte[1];
	len[0] = (byte) ( ( lenint[0] >>> 0) & 0xff );


	// ** construct the byte used for calculating the CRC
	if (flag[1].equals("1")){

		if(intcommand==14){
			byte[] ba = {stxB[0], flagValue[3], command[0], tagTypeB[0], tag[0],
							tag[1], tag[2], tag[3], tag[4], tag[5] ,tag[6], tag[7]};
			CRCcalc(ba);

		}
		if(intcommand==24){
			byte[] ba =  {stxB[0], flagValue[3], command[0], tagTypeB[0], tag[0],
							tag[1], tag[2], tag[3], tag[4], tag[5], tag[6],tag[7],
							startB[0], numB[0]};
			CRCcalc(ba);
		}
		if(intcommand==44){
			byte[] ba = {stxB[0],  flagValue[3], command[0], tagTypeB[0], tag[0],
							tag[1], tag[2], tag[3], tag[4], tag[5], tag[6],tag[7],
							startB[0], numB[0], data[0], data[1], data[2], data[3]};
			CRCcalc(ba);
		}


	}
	else {

		if (intcommand==14){
			byte[] ba = {stxB[0], flagValue[3], command[0], tagTypeB[0]};

			CRCcalc(ba);

		}
		if (intcommand==24){
			byte[] ba = {stxB[0], flagValue[3], command[0], tagTypeB[0],
						startB[0], numB[0]};
			CRCcalc(ba);


		}
		if(intcommand==44){
			byte[] ba = {stxB[0], flagValue[3], command[0], tagTypeB[0],
						startB[0], numB[0], data[0], data[1], data[2], data[3]};
			CRCcalc(ba);
		}

	}



} // end main



	// ** Method for CRC calculation
	public static void CRCcalc(byte[] b){

		int x,y;
		int crc_16 = 0x0000;
		int compare = 0x0001;

		for (x=1; x < b.length; x++){
			crc_16 ^=b[x];

			for (y=0; y<8; y++){
				if ((crc_16 & compare) == 1){
					crc_16>>=1;
					crc_16 ^=0x8408;
				}
				else {
					crc_16>>=1;
				}
			}
		}

	System.out.println("CRC = " + crc_16);
	System.out.println("HexCRC = " + Integer.toHexString(crc_16));
	} // ** end of method



   public static void printBytes(byte[] ba){
	   for (int i = 0; i<ba.length; i++){
		   System.out.print(ba[i]);
	   }
	   System.out.println("\n");
   }


} // end class



