#include "includes.h"


/**
* @name   两字节CRC校验
* @param  
		aStr  需要校验的数组首地址
		len   数组总长度
* @retval 无
* @brief  无
*/
void NetCRC16(uint8_t *aStr ,uint16_t len)
{
	uint16_t alen = len-2;   //CRC16
    uint16_t xda , xdapoly ;
    uint16_t i,j, xdabit ;
    xda = 0xFFFF ;
	xdapoly = 0xA001 ;	// (X**16 + X**15 + X**2 + 1)
    for(i=0;i<alen;i++) 
    {
		xda ^= aStr[i] ;
		for(j=0;j<8;j++) 
		{
			xdabit = (uint8_t )(xda & 0x01) ;
			xda >>= 1 ;
			if( xdabit ) xda ^= xdapoly ;
		}
	}
    aStr[alen] = (uint8_t)(xda & 0xFF) ;
    aStr[alen+1] = (uint8_t)(xda>>8) ;
}

/*******************************************************************************
* Function Name  : SRAM_CRC16
* Description    : CRC校验 - 读取SRAM中数据
* Input          : 
			
			len 	: 数据的长度 -- Flash中的数据校验一般是512Byte
* Return         : 数据的校验值
*******************************************************************************/
uint16_t SRAM_CRC16(uint32_t addr,uint16_t len)
{
    uint16_t xda , xdapoly ;
    uint16_t i, j, xdabit ;
    xda = 0xFFFF ;
    xdapoly = 0xA001 ;  // (X**16 + X**15 + X**2 + 1)
    for (i = 0; i < len; i++)
    {
        xda ^= SRAM_Read_Byte(addr+i) ;
        for (j = 0; j < 8; j++)
        {
            xdabit = (unsigned char)(xda & 0x01) ;
            xda >>= 1 ;
            if ( xdabit ) xda ^= xdapoly ;
        }
    }
    return xda;
}

/*******************************************************************************
* Function Name  : NetCRC16_2
* Description    : CRC校验 - 读取SRAM中数据
* Input          : 
			aStr  	: 需要校验的数组首地址
			len 	: 数据的长度 -- Flash中的数据校验一般是512Byte
* Return         : 数据的校验值
*******************************************************************************/
uint16_t NetCRC16_2(uint8_t *aStr ,uint16_t len)
{
    uint16_t xda , xdapoly ;
    uint16_t i,j, xdabit ;
    xda = 0xFFFF ;
	xdapoly = 0xA001 ;	// (X**16 + X**15 + X**2 + 1)
    for(i=0;i<len;i++) 
    {
		xda ^= aStr[i] ;
		for(j=0;j<8;j++) 
		{
			xdabit = (uint8_t )(xda & 0x01) ;
			xda >>= 1 ;
			if( xdabit ) xda ^= xdapoly ;
		}
	}
	return xda;
}

/*******************************************************************************
* Function Name  : NetCRC16_Data
* Description    : CRC校验 - CRC在检验数据中
* Input          : 
	aStr  	: 需要校验的数组首地址
	len 	: 数据的长度 -- Flash中的数据校验一般是512Byte
	crc_id	：CRC在数组中的下标位置，低地址在前
* Return         : 数据的校验值
*******************************************************************************/
uint16_t NetCRC16_Data(uint8_t *aStr ,uint16_t len,uint16_t crc_id)
{
	uint16_t xda , xdapoly ;
    uint16_t i,j, xdabit ;
    xda = 0xFFFF ;
	xdapoly = 0xA001 ;	// (X**16 + X**15 + X**2 + 1)
    for(i=0;i<len;i++) 
    {
		if((i == crc_id) || (i == (crc_id + 1)))
		{
			xda ^= 0x00;
		}else {
			xda ^= aStr[i];
		}
		
		for(j=0;j<8;j++) 
		{
			xdabit = (uint8_t )(xda & 0x01) ;
			xda >>= 1 ;
			if( xdabit ) xda ^= xdapoly ;
		}
	}
	
	return xda;
}

/*******************************************************************************
* Function Name  : 用于网络升级时对flash的数据计算CRC
* Description    : CRC校验 - 读取SRAM中数据
* Input          : 
			aStr  	: 需要校验的数组首地址
			len 	: 数据的长度 -- Flash中的数据校验一般是512Byte
* Return         : 数据的校验值
*******************************************************************************/
//uint16_t FlashData_NetCRC16(uint32_t FlashAddr ,uint8_t* aStr ,uint16_t len)
//{
//    uint16_t xda , xdapoly;
//    uint16_t i,j, xdabit ;
//    xda = 0xFFFF ;
//		xdapoly = 0xA001 ;	// (X**16 + X**15 + X**2 + 1)
//    for(i=0;i<len;i++) 
//    {
//			if((len %512) == 0)
//			{
//				WDT_Feed();
//				Flash_Read(aStr, 512, FlashAddr);
//				FlashAddr += 512;
//			}
//			
//			xda ^= aStr[i%512];
//			for(j=0;j<8;j++) 
//			{
//				xdabit = (uint8_t )(xda & 0x01) ;
//				xda >>= 1 ;
//				if( xdabit ) xda ^= xdapoly ;
//			}
//	}
//	return xda;
//}

/*******************************************************************************
* Function Name  : 用于网络升级时对flash的数据计算CRC
* Description    : CRC校验 - 读取SRAM中数据
* Input          : 
			aStr  	: 需要校验的数组首地址
			len 	: 数据的长度 -- Flash中的数据校验一般是512Byte
* Return         : 数据的校验值
*******************************************************************************/
uint16_t FlashData_NetCRC16(uint32_t FlashAddr, uint16_t len)
{
    uint16_t xda , xdapoly;
    uint16_t i,j, xdabit ;
	uint8_t Fdata =0; 
    xda = 0xFFFF ;
	xdapoly = 0xA001 ;	// (X**16 + X**15 + X**2 + 1)
    for(i=0;i<len;i++) 
    {
			Flash_Read(&Fdata, 1, FlashAddr++);
			xda ^= Fdata;
			for(j=0;j<8;j++) 
			{
				xdabit = (uint8_t )(xda & 0x01) ;
				xda >>= 1 ;
				if( xdabit ) xda ^= xdapoly ;
			}
	}
	return xda;
}

/*******************************************************************************
* Function Name  : UDP_Data_Pack_CRC16
* Description    : UDP服务器协议数据CRC校验函数 - 
与正常的CRC校验有些不同，CRC在包头内部，在校验过程需要将CRC值默认为零计算正确的CRC16的值
* Input          : 
	aStr  	: 需要校验的数组首地址
	len 	: 数据的长度 
* Return         : None
*******************************************************************************/
uint16_t UDP_Data_Pack_CRC16(uint8_t *aStr ,uint16_t len)
{
	uint16_t alen = len;   	//CRC16
    uint16_t xda , xdapoly ;
    uint16_t i,j, xdabit ;
    xda = 0xFFFF ;
	xdapoly = 0xA001 ;	// (X**16 + X**15 + X**2 + 1)
    for(i=0;i<alen;i++) 
    {
		xda ^= aStr[i];
		
		for(j=0;j<8;j++) 
		{
			xdabit = (uint8_t )(xda & 0x01) ;
			xda >>= 1 ;
			if( xdabit ) xda ^= xdapoly ;
		}
	}
    return xda;
}

/*******************************************************************************
* Function Name  : Dev_CheckSum 
* Description    : 和校验取反，数据内容从SRAM中读取
*******************************************************************************/
uint8_t Dev_CheckSum(uint32_t addr,uint16_t len)
{
	uint8_t data_sum = 0;
	uint8_t check_temp_buff[SRAM_Device_List_Size] = {0};
	
	SRAM_Read_Buff(check_temp_buff,len,addr);
	
	for(uint16_t i = 0;i<len;i++)
	{
		data_sum += check_temp_buff[i];
	}
	return ~data_sum;
}

/**@name  两个数组和校验取反
	*@para
  *  Data1 		 数据包1
  *  Data1Len  数据包1的长度
  *  Data2     数据包2
  *  Data2Len  数据包2的长度
  *@ret  data_sum
	*/
uint8_t DoubleData_CheckSum(uint8_t *Data1, uint16_t Data1Len, uint8_t *Data2, uint16_t Data2Len)
{
	uint8_t data_sum = 0;
	uint16_t i;
	
	for(i = 0; i < Data1Len;i++)
	{
		data_sum += Data1[i];
	}
	
	for(i = 0; i < Data2Len; i++)
	{
		data_sum += Data2[i];
	}
	
	return ~data_sum;
}

/*******************************************************************************
* Function Name  : CheckSum 
* Description    : 和校验取反
*******************************************************************************/
uint8_t CheckSum(uint8_t *data,uint16_t len)
{
	uint8_t data_sum = 0;
	
	for(uint16_t i = 0;i<len;i++)
	{
		data_sum += data[i];
	}
	return ~data_sum;
}

/*******************************************************************************
* Function Name  : CheckSum_Overlook_Check 
* Description    : 和校验取反,忽略校验字本身
* input: data: 数据指针
				 len ：数据总长度
		 check_id: 校验数据所在下标
*******************************************************************************/
uint8_t CheckSum_Overlook_Check(uint8_t *data, uint16_t len, uint16_t check_id)
{
	uint8_t data_sum = 0;
	
	for(uint16_t i = 0;i<len;i++)
	{
		if(check_id != i) data_sum += data[i];
	}
	return ~data_sum;
}

/*******************************************************************************
* Function Name  : CheckSum_Overlook_Check_2 
* Description    : 和校验,忽略校验字本身
* input: data: 数据指针
				 len ：数据总长度
		 check_id: 校验数据所在下标
*******************************************************************************/
uint8_t CheckSum_Overlook_Check_2(uint8_t *data, uint16_t len, uint16_t check_id)
{
	uint8_t data_sum = 0;
	
	for(uint16_t i = 0;i<len;i++)
	{
		if(check_id != i) data_sum += data[i];
	}
	return data_sum;
}

/*******************************************************************************
* Function Name  : SOR_CRC 
* Description    : 和校验，数据内容从SRAM中读取
*******************************************************************************/
uint8_t SOR_SRAM_CRC(uint32_t Dataaddr, uint8_t DataLen)
{
	uint8_t i;
	uint8_t sor_data = 0;
	
	for(i = 0; i < DataLen; i++)
	{
		sor_data += SRAM_Read_Byte(Dataaddr+i);;
	}
	return sor_data; 
}

/*******************************************************************************
* Function Name  : SOR_CRC 
* Description    : 和校验
*******************************************************************************/
uint8_t SOR_CRC(uint8_t *Data, uint8_t DataLen)
{
	uint8_t i;
	uint8_t sor_data = 0;

	for(i = 0; i < DataLen; i++)//i可能为0 ，也可以是1
	{
		sor_data = sor_data+Data[i];
	}
	return sor_data;
}

/*******************************************************************************
* Function Name  : Device_Data_Check 
* Description    : 设备链表数据校验
*******************************************************************************/
uint8_t Device_Data_Check(uint32_t sram_addr)
{
	uint16_t data_len = SRAM_Read_Word(sram_addr + Dev_DataLen);
	uint8_t data_sum = 0;
	if(data_len > SRAM_Device_List_Size)	return 1;
	
	uint8_t check_temp_buff[SRAM_Device_List_Size] = {0};
	
	SRAM_Read_Buff(check_temp_buff,data_len,sram_addr);
	
	for(uint16_t i = 0;i<data_len;i++)
	{
		data_sum += check_temp_buff[i];
	}
	return ~data_sum;
}



/*******************************************************************************
* Function Name  : CheckSum_Overlook_Check 
* Description    : 和校验取反,忽略校验字本身
* input: data: 数据指针
				 len ：数据总长度
		 check_id: 校验数据所在下标
*******************************************************************************/
uint8_t SRAM_CheckSum_Overlook_Check(uint32_t addr, uint16_t len, uint16_t check_id)
{
	uint8_t data_sum = 0;
	
	for(uint16_t i = 0;i<len;i++)
	{
		if(check_id != i) data_sum += SRAM_Read_Byte(addr+i) ;
	}
	return ~data_sum;
}

/*----------------------------------------------------------*/
/*函数名：CRC_168                                          */
/*参  数：无                                                 */
/*返回值：校验值                                                 */
/*-----------------------------------------------------------*/
uint8_t CRC_168(uint8_t * data_buf, uint16_t datalen)
{
    uint8_t  CRC_Val = 0;
    uint8_t i=0;
    uint32_t sum = 0;

    while(datalen--)
    {
        sum += data_buf[i];
        i++;
    }
    CRC_Val = sum%168;
    return CRC_Val;
}

/**
*@name NetCRC8  一个字节异或校验
*@para 
*   aStr  需要校验的数组
*   len   数组总长度
*@Ret 无
*@attention 数组的末尾存放校验值
*/
void NetCRC8( uint8_t *aStr ,uint16_t len)
{
	uint8_t i;
	uint8_t xda;
//	u8 sum = 0;
	xda = 0x00;
	for(i = 0; i < len-1; i++)
	{
//		xda ^= aStr[i];
//		sum += xda;
		xda = xda ^ aStr[i];

	}
	
	aStr[len-1] = xda;
}
/**
*@name GetCRC8  一个字节异或校验
*@para 
*   aStr  需要校验的数组
*   len   数组总长度
*@Ret 异或校验值
*@attention 整个数组进行计算
*/
uint8_t GetCRC8(uint8_t *aStr, uint16_t len)
{
	uint8_t i;
	uint8_t xda;
//	u8 sum = 0;
	xda = 0x00;
	for(i = 0; i < len; i++)
	{
//		xda ^= aStr[i];
//		sum += xda;
		xda = xda ^ aStr[i];

	}
	
	return xda;
}


/**@name  BLV SN号得到函数
	*@para
  *  SnValue   Sn当前值
  *  SnMin     Sn号最小值
  *  SnMax     Sn号最大值
	*/
uint8_t BLV_SN_Get(uint8_t *SnValue, uint8_t SnMin, uint8_t SnMax)
{
	if((*SnValue < SnMax)&&(*SnValue >= SnMin))   //Sn号
	{
		(*SnValue)++;
	}
	else
	{
		*SnValue = SnMin;
	}	
	return *SnValue;
}

