#include "fm_samsung_ecc.h"
#include "flash.h"
extern TFFSize ffsize;	
void FlashEccGen(unsigned char *write_data, unsigned char *eccGen)
{
	unsigned int i, j;
	unsigned char tmp, tmp2;
	unsigned char data_table0[16];
	unsigned char data_table1[16];
	unsigned char sum, paritc;
	unsigned char parit0c, parit1c, parit2c, parit3c;
	unsigned char parit4c, parit5c, parit6c, parit7c;
	unsigned char parit1_1, parit1_2, parit2_1, parit2_2, parit4_1, parit4_2;
	unsigned char parit8_1, parit8_2, parit16_1, parit16_2, parit32_1, parit32_2;
	unsigned char parit64_1, parit64_2, parit128_1, parit128_2, parit256_1, parit256_2;
	unsigned char parit512_1, parit512_2, parit1024_1, parit1024_2, parit2048_1, parit2048_2;
	static unsigned char paritr[512];
	
	tmp = 0;
	tmp2 = 0;
	paritc = 0; 
	sum = 0;
	
	parit0c = 0;
	parit1c = 0;
	parit2c = 0;
	parit3c = 0;
	parit4c = 0;
	parit5c = 0;
	parit6c = 0;
	parit7c = 0;
	
	parit8_1 = 0;
	parit8_2 = 0;
	parit16_1 = 0;
	parit16_2 = 0;
	parit32_1 = 0;
	parit32_2 = 0;
	parit64_1 = 0;
	parit64_2 = 0;
	parit128_1 = 0;
	parit128_2 = 0;
	parit256_1 = 0;                                                                                                  	
	parit256_2 = 0;                                                                                                  
	parit512_1 = 0;
	parit512_2 = 0;
	parit1024_1 = 0;
	parit1024_2 = 0;
	parit2048_1 = 0;                                                                        
	parit2048_2 = 0;		
	                                                 
	data_table0[0]  = 0;
	data_table0[1]  = 1;
	data_table0[2]  = 1;
	data_table0[3]  = 0;
	data_table0[4]  = 1;
	data_table0[5]  = 0;
	data_table0[6]  = 0;
	data_table0[7]  = 1;
	data_table0[8]  = 1;
	data_table0[9]  = 0;
	data_table0[10] = 0;
	data_table0[11] = 1;
	data_table0[12] = 0;
	data_table0[13] = 1;
	data_table0[14] = 1;
	data_table0[15] = 0;
	
	data_table1[0]  = 1;
	data_table1[1]  = 0;
	data_table1[2]  = 0;
	data_table1[3]  = 1;
	data_table1[4]  = 0;
	data_table1[5]  = 1;
	data_table1[6]  = 1;
	data_table1[7]  = 0;
	data_table1[8]  = 0;
	data_table1[9]  = 1;
	data_table1[10] = 1;
	data_table1[11] = 0;
	data_table1[12] = 1;
	data_table1[13] = 0;
	data_table1[14] = 0;
	data_table1[15] = 1;

	for (i = 0; i < 512; i++)
	{
		paritc = paritc ^ (*(write_data+i));

		tmp  = (*(write_data+i) & 0xf0) >> 4;
		tmp2 = *(write_data+i) & 0x0f;

		if (tmp == 0)
			*(paritr + i) = *(data_table0 + tmp2);
		else if (tmp == 1)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 2)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 3)
			*(paritr + i) = *(data_table0 + tmp2);
		else if (tmp == 4)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 5)
			*(paritr + i) = *(data_table0 + tmp2);
		else if (tmp == 6)
			*(paritr + i) = *(data_table0 + tmp2);
		else if (tmp == 7)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 8)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 9)
			*(paritr + i) = *(data_table0 + tmp2);
		else if (tmp == 10)
			*(paritr + i) = *(data_table0 + tmp2);
		else if (tmp == 11)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 12)
			*(paritr + i) = *(data_table0 + tmp2);
		else if (tmp == 13)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 14)
			*(paritr + i) = *(data_table1 + tmp2);
		else if (tmp == 15)
			*(paritr + i) = *(data_table0 + tmp2);
	}
             
	parit0c = ((paritc & 0x01) ? 1 : 0);
	parit1c = ((paritc & 0x02) ? 1 : 0);
	parit2c = ((paritc & 0x04) ? 1 : 0);
	parit3c = ((paritc & 0x08) ? 1 : 0);
	parit4c = ((paritc & 0x10) ? 1 : 0);
	parit5c = ((paritc & 0x20) ? 1 : 0);
	parit6c = ((paritc & 0x40) ? 1 : 0);
	parit7c = ((paritc & 0x80) ? 1 : 0);

	parit1_2 = parit6c ^ parit4c ^ parit2c ^ parit0c;
	parit1_1 = parit7c ^ parit5c ^ parit3c ^ parit1c;
	parit2_2 = parit5c ^ parit4c ^ parit1c ^ parit0c;
	parit2_1 = parit7c ^ parit6c ^ parit3c ^ parit2c;
	parit4_2 = parit3c ^ parit2c ^ parit1c ^ parit0c;
	parit4_1 = parit7c ^ parit6c ^ parit5c ^ parit4c;

	for (i = 0; i < 512; i++)
		sum = sum ^ (*(paritr+i));

	for (i = 0; i < 512; i = i + 2)
		parit8_2 = parit8_2 ^ (*(paritr + i));
		
	for (i = 0; i < 512; i = i + 4)
	{
		parit16_2 = parit16_2 ^ (*(paritr + i));
		parit16_2 = parit16_2 ^ (*(paritr + i + 1));
	}
	for (i = 0; i < 512; i = i + 8)
	{
		for (j = 0; j <= 3; j++)
			parit32_2 = parit32_2 ^ (*(paritr + i + j));
	}
	for (i = 0; i < 512; i = i + 16)
	{
		for (j = 0; j <= 7; j++)
			parit64_2 = parit64_2 ^ (*(paritr + i + j));
	}
	for (i = 0; i < 512; i = i + 32)
	{
		for (j = 0; j <= 15; j++)
			parit128_2 = parit128_2 ^ (*(paritr + i + j));
	}
	for (i = 0; i < 512; i = i + 64)
	{
		for (j = 0; j <= 31; j++)
			parit256_2 = parit256_2 ^ (*(paritr + i + j));
	}
	for (i = 0; i < 512; i = i + 128)
	{
		for (j = 0; j <= 63; j++)
			parit512_2 = parit512_2 ^ (*(paritr + i + j));
	}
	for (i = 0; i < 512;i = i + 256)
	{
		for (j = 0; j <= 127; j++)
			parit1024_2 = parit1024_2 ^ (*(paritr + i + j));
	}

	for (i = 0; i < 512; i = i + 512)
	{
		for (j = 0; j <= 255; j++)
			parit2048_2 = parit2048_2 ^ (*(paritr + i + j));
	}
            
	if (sum == 0)
	{
		parit2048_1 = parit2048_2;
		parit1024_1 = parit1024_2;
		parit512_1 = parit512_2;
		parit256_1 = parit256_2;
		parit128_1 = parit128_2;
		parit64_1 = parit64_2;
		parit32_1 = parit32_2;
		parit16_1 = parit16_2;
		parit8_1 = parit8_2;
	}
	else
	{
		parit2048_1 = (parit2048_2 ? 0 : 1);
		parit1024_1 = (parit1024_2 ? 0 : 1);
		parit512_1  = (parit512_2  ? 0 : 1);
		parit256_1  = (parit256_2  ? 0 : 1);
		parit128_1  = (parit128_2  ? 0 : 1);
		parit64_1   = (parit64_2   ? 0 : 1);
		parit32_1   = (parit32_2   ? 0 : 1);
		parit16_1   = (parit16_2   ? 0 : 1);
		parit8_1    = (parit8_2    ? 0 : 1);
	}
            
	parit2048_2 <<= 0;
	parit2048_1 <<= 1;
	parit1_2 <<= 2;
	parit1_1 <<= 3;
	parit2_2 <<= 4;
	parit2_1 <<= 5;
	parit4_2 <<= 6;
	parit4_1 <<= 7;

	parit8_2 <<= 0;
	parit8_1 <<= 1;
	parit16_2 <<= 2;
	parit16_1 <<= 3;
	parit32_2 <<= 4;
	parit32_1 <<= 5;
	parit64_2 <<= 6;
	parit64_1 <<= 7;

	parit128_2 <<= 0;
	parit128_1 <<= 1;
	parit256_2 <<= 2;
	parit256_1 <<= 3;
	parit512_2 <<= 4;
	parit512_1 <<= 5;
	parit1024_2 <<= 6;
	parit1024_1 <<= 7;

	*(eccGen + 0) = ~(parit64_1 | parit64_2 | parit32_1 | parit32_2 | parit16_1 | parit16_2 | parit8_1 | parit8_2);
	*(eccGen + 1) = ~(parit1024_1 | parit1024_2 | parit512_1 | parit512_2 | parit256_1 | parit256_2 | parit128_1 | parit128_2);
	*(eccGen + 2) = ~(parit4_1 | parit4_2 | parit2_1 | parit2_2 | parit1_1 | parit1_2 | parit2048_1 | parit2048_2);
}

unsigned int FlashEccCheck(unsigned char *pageData, unsigned char* ecc_data1, unsigned char* ecc_data2)    //Checking ECC if there exists difference in ECC value
{
	unsigned int i;
	unsigned char tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
	unsigned char comp0_bit[8], comp1_bit[8], comp2_bit[8];
	unsigned char tmp[3];
	unsigned char ecc_bit[24];
	unsigned char ecc_sum;
	unsigned char ecc_value, find_bit;
	unsigned int  find_byte;
   
   	ecc_sum = 0;
   	find_bit = 0; 
   	find_byte = 0;
   
	for (i = 0; i <= 2; i++)
	{
		*(ecc_data1 + i) = ~(*(ecc_data1 + i));
		*(ecc_data2 + i) = ~(*(ecc_data2 + i));
	}           
	
	tmp0_bit[0] = *ecc_data1 % 2;	
	*ecc_data1  = *ecc_data1 / 2;     
	
	tmp0_bit[1] = *ecc_data1 % 2;
	*ecc_data1  = *ecc_data1 / 2;
	
	tmp0_bit[2] = *ecc_data1 % 2;
	*ecc_data1  = *ecc_data1 / 2;
			
	tmp0_bit[3] = *ecc_data1 % 2;
	*ecc_data1  = *ecc_data1 / 2;
			
	tmp0_bit[4] = *ecc_data1 % 2;
	*ecc_data1  = *ecc_data1 / 2;
			
	tmp0_bit[5] = *ecc_data1 % 2;
	*ecc_data1  = *ecc_data1 / 2;
			
	tmp0_bit[6] = *ecc_data1 % 2;
	*ecc_data1  = *ecc_data1 / 2;
			
	tmp0_bit[7] = *ecc_data1 % 2;
	

	tmp1_bit[0] = *(ecc_data1 + 1) % 2;
	*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
			
	tmp1_bit[1] = *(ecc_data1 + 1) % 2;
	*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
			
	tmp1_bit[2] = *(ecc_data1 + 1) % 2;
	*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
			
	tmp1_bit[3] = *(ecc_data1 + 1) % 2;
	*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
			
	tmp1_bit[4] = *(ecc_data1 + 1) % 2;
	*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
			
	tmp1_bit[5] = *(ecc_data1 + 1) % 2;
	*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
			
	tmp1_bit[6] = *(ecc_data1 + 1) % 2;
	*(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
			
	tmp1_bit[7] = *(ecc_data1 + 1) % 2;

	tmp2_bit[0] = *(ecc_data1 + 2) % 2;
	*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
			
	tmp2_bit[1] = *(ecc_data1 + 2) % 2;
	*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
			
	tmp2_bit[2] = *(ecc_data1 + 2) % 2;
	*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
			
	tmp2_bit[3] = *(ecc_data1 + 2) % 2;
	*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
			
	tmp2_bit[4] = *(ecc_data1 + 2) % 2;
	*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
			
	tmp2_bit[5] = *(ecc_data1 + 2) % 2;
	*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
			
	tmp2_bit[6] = *(ecc_data1 + 2) % 2;
	*(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
			
	tmp2_bit[7] = *(ecc_data1 + 2) % 2;

	comp0_bit[0] = *ecc_data2 % 2;
	*ecc_data2 = *ecc_data2 / 2;
	comp0_bit[1] = *ecc_data2 % 2;
	*ecc_data2 = *ecc_data2 / 2;
	comp0_bit[2] = *ecc_data2 % 2;
	*ecc_data2 = *ecc_data2 / 2;
	comp0_bit[3] = *ecc_data2 % 2;
	*ecc_data2 = *ecc_data2 / 2;
	comp0_bit[4] = *ecc_data2 % 2;
	*ecc_data2 = *ecc_data2 / 2;
	comp0_bit[5] = *ecc_data2 % 2;
	*ecc_data2 = *ecc_data2 / 2;
	comp0_bit[6] = *ecc_data2 % 2;
	*ecc_data2 = *ecc_data2 / 2;
	comp0_bit[7] = *ecc_data2 % 2;

	comp1_bit[0] = *(ecc_data2 + 1) % 2;
	*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
	comp1_bit[1] = *(ecc_data2 + 1) % 2;
	*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
	comp1_bit[2] = *(ecc_data2 + 1) % 2;
	*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
	comp1_bit[3] = *(ecc_data2 + 1) % 2;
	*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
	comp1_bit[4] = *(ecc_data2 + 1) % 2;
	*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
	comp1_bit[5] = *(ecc_data2 + 1) % 2;
	*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
	comp1_bit[6] = *(ecc_data2 + 1) % 2;
	*(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
	comp1_bit[7] = *(ecc_data2 + 1) % 2;

	comp2_bit[0] = *(ecc_data2 + 2) % 2;
	*(ecc_data2 + 2)=*(ecc_data2 + 2) / 2;
	comp2_bit[1] = *(ecc_data2 + 2) % 2;
	*(ecc_data2 + 2)=*(ecc_data2 + 2) / 2;
	comp2_bit[2] = *(ecc_data2 + 2) % 2;
	*(ecc_data2 + 2)=*(ecc_data2 + 2) / 2;
	comp2_bit[3] = *(ecc_data2 + 2) % 2;
	*(ecc_data2 + 2)=*(ecc_data2 + 2) / 2;
	comp2_bit[4] = *(ecc_data2 + 2) % 2;
	*(ecc_data2 + 2)=*(ecc_data2 + 2) / 2;
	comp2_bit[5] = *(ecc_data2 + 2) % 2;
	*(ecc_data2 + 2)=*(ecc_data2 + 2) / 2;
	comp2_bit[6] = *(ecc_data2 + 2) % 2;
	*(ecc_data2 + 2)=*(ecc_data2 + 2) / 2;
	comp2_bit[7] = *(ecc_data2 + 2) % 2;
	
	for (i = 0; i < 6; i++)
		ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
		
	for (i = 0; i < 8; i++)
		ecc_bit[i + 6]= tmp0_bit[i] ^ comp0_bit[i];
		
	for (i = 0; i < 8; i++)	
		ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
				
	ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
	ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];

	for (i = 0; i < 24; i++)
		ecc_sum += ecc_bit[i];
		
	if (ecc_sum == 12)
	{
	   	find_byte = (ecc_bit[23] << 8) + (ecc_bit[21] << 7) + (ecc_bit[19] << 6) + (ecc_bit[17] << 5) + 
	   		(ecc_bit[15] << 4) + (ecc_bit[13] << 3) + (ecc_bit[11] << 2) + (ecc_bit[9] << 1) + ecc_bit[7];
	   	find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
	   	ecc_value = (pageData[find_byte] >> find_bit) % 2;

	   	if (ecc_value == 0) 
	   		ecc_value = 1;
	   	else
	   		ecc_value = 0;

	   	*tmp = pageData[find_byte];
	   	tmp0_bit[0] = *tmp % 2;
		*tmp = *tmp / 2;
	   	tmp0_bit[1] = *tmp % 2;
		*tmp = *tmp / 2;
	   	tmp0_bit[2]= *tmp % 2;
		*tmp = *tmp / 2;
	   	tmp0_bit[3]= *tmp % 2;
		*tmp = *tmp / 2;
	   	tmp0_bit[4]= *tmp % 2;
		*tmp = *tmp / 2;
	   	tmp0_bit[5]= *tmp % 2;
		*tmp = *tmp / 2;
	   	tmp0_bit[6]= *tmp % 2;
		*tmp = *tmp / 2;
	   	tmp0_bit[7]= *tmp % 2;
	   	tmp0_bit[find_bit] = ecc_value;

	   	*tmp = (tmp0_bit[7] << 7) + (tmp0_bit[6] << 6) + (tmp0_bit[5] << 5) + (tmp0_bit[4] << 4) +
	   		(tmp0_bit[3] << 3) + (tmp0_bit[2] << 2) + (tmp0_bit[1] << 1) + tmp0_bit[0];
		   
	   	pageData[find_byte] = *tmp;
	   	return 1;
	}
	return 0;
}
