/************************************************************************
*
* 文件名   ：  FFFE.c
* 版权说明 ：  北京瑞安时代科技有限责任公司 
* 版本号   ：  1.0  
* 创建时间 ：  2009.08.17
* 作者     ：  车载及协议部
* 功能描述 ：  FFFE协议转义及接收文件 
* 使用注意 ：  所能处理的长度为65535，因为受长度的类型UINT16限制。
* 修改记录 ：  20120706,增加了FFFEPack函数
*
************************************************************************/

#include "FFFE.h"
#include "stdlib.h"

/*FFFE解转义状态*/
#define WAIT_FF_C1 0x00u
#define WAIT_FF_C2 0x01u
#define WAIT_NO_FF 0x02u
#define WAIT_FF_POS 0x03u
#define ABNORMAL_STATE 0x04u

/*FFFE数据接收状态*/
#define COM_WAIT_START_FF 0x00u
#define COM_WAIT_START_FE 0x01u
#define COM_WAIT_STOP_FF 0x02u
#define COM_WAIT_STOP_FD 0x03u

/*
* 功能描述： 将数据进行FFFE转义处理（不加头FFFE及尾FFFD）。
* 输入参数： const UINT8 *pSrc    数据(无FFFE转义)
*            UINT16 SrcLen        数据(无FFFE转义)的长度
* 输出参数： UINT8 *pTgt          数据(经过FFFE转义)
* 返回值：   转义后的长度   
*/
UINT16 TranslateToFFFE(const UINT8 *pSrc, UINT8 *pTgt,UINT16 SrcLen)
{
    UINT16 SrcPos = 0u;
    UINT16 TgtPos = 0u;
    UINT16 Pos1 = 0u;/*前一个FF的位置*/
    UINT16 Pos2 = 0u;/*后一个FF的位置*/
    UINT16 iii = 0u;/*临时计数变量*/
    UINT16 Gap = 0u;/*两个FF之间的字节数*/
    UINT8 Got1stFF = 0u;/*1-获得前一个FF；0-未获得前一个FF*/
    UINT8 Got2ndFF = 0u;/*1-获得后一个FF；0-未获得后一个FF*/

	if ((NULL == pSrc) || (NULL == pTgt))
	{
		; /*入口参数错误*/
	} 
	else
	{

		for(SrcPos=0u;SrcPos<SrcLen;SrcPos++)
		{
			if(1u == Got1stFF)
			{
				if(0xFFu == pSrc[SrcPos])
				{
					/*已遇到前一个FF，且当前又遇到FF*/
					Got2ndFF = 1u;
					Pos2 = SrcPos;
					pTgt[TgtPos]=(UINT8)(Pos2-Pos1);
					TgtPos++;

					for(iii=Pos1+1u;iii<Pos2;iii++)
					{
						pTgt[TgtPos]=pSrc[iii];
						TgtPos++;
					}

					Got1stFF=0u;
					Got2ndFF=0u;
					Pos1=0u;
					Pos2=0u;
					Gap=0u;
				}
				else
				{
					/*已遇到前一个FF，且当前遇到非FF*/
					Gap++;
					if(252u == Gap)
					{
						Got1stFF=0u;
						Gap=0u;
						pTgt[TgtPos]=0u;
						TgtPos++;
						for(iii=Pos1+1u;iii<=SrcPos;iii++)
						{
							pTgt[TgtPos]=pSrc[iii];
							TgtPos++;
						}
					}
					else
					{
					}
				}
			}
			else
			{
				/*尚未遇到前一个FF*/
				pTgt[TgtPos]=pSrc[SrcPos];
				TgtPos++;
				if(0xFFu == pSrc[SrcPos])   
				{
					/*遇到前一个FF*/
					Got1stFF=1u;
					Pos1=SrcPos;
					Gap=0u;
				}
				else
				{
				}
			}
		}
		/*已经遇到了前一个FF, 且源数据已到了末尾仍未遇到后一个FF*/
		if(1u == Got1stFF)
		{
			pTgt[TgtPos] = 0u;
			TgtPos++;

			for(iii=Pos1+1u;iii<SrcLen;iii++)
			{
				pTgt[TgtPos]=pSrc[iii];
				TgtPos++;
			}
		}
		else
		{
			; /*继续执行*/
		}
	}
    return TgtPos;
}


/*
* 功能描述：  将经过FFFE转义处理后的数据（已经去掉了头FFFE及尾FFFD）还原为原始数据
* 输入参数：  const UINT8 *pSrc,    数据(FFFE转义)
*             UINT16 SrcLen,        数据(FFFE转义)的长度
* 输出参数：  UINT8 *pTgt,          数据(去掉FFFE转义)
* 返回值：    大于0,  转义成功,返回转义后的数据长度
*             0,   有不能转义的字符，转义失败。或者转义后的数据长度为0   
*/
UINT16 TranslateFromFFFE(const UINT8 *pSrc,UINT8 *pTgt,UINT16 SrcLen)
{
    UINT16 SrcPos=0u;
    UINT16 TgtPos=0u;
    UINT16 NonFFCount=0u;/*进入WAIT_NO_FF状态的次数*/
    UINT16 NextFFPos=0u;/*下一个FF字符的位置*/
    UINT8 Char=0u;/*当前字符值*/
    UINT8 State=WAIT_FF_C1;/*状态*/

    for(SrcPos=0u;SrcPos<SrcLen;SrcPos++)
    {
        Char=pSrc[SrcPos];
        switch(State)
        {
        case WAIT_FF_C1:
            /*等待FF序列第一FF字符*/

            if(0xFFu == Char)  
            {
                /*收到FF字符*/
                pTgt[TgtPos]=Char;
                TgtPos++;
                State = WAIT_FF_C2;
            }
            else
            {
                /*当前非FF字符*/
                pTgt[TgtPos]=Char;
                TgtPos++;
            }

            break;
        case WAIT_FF_C2:
            /*等待FF序列第二FF字符*/

            if( (0xFDu==Char) || (0xFEu==Char) || (0xFFu==Char) )
            {
                State = ABNORMAL_STATE;
            }
            else
            {
                if(0u == Char)
                {
                    State = WAIT_NO_FF;
                }
                else
                {
                    if(1u == Char)
                    {
                        pTgt[TgtPos]=0xffu;
                        TgtPos++;
                        State = WAIT_FF_C1;
                    }
                    else
                    {
                        NextFFPos=SrcPos+Char-1u;
                        State = WAIT_FF_POS;
                    }
                }
            }
            break;
        case WAIT_NO_FF:
            /*消息中不再有FF字符需要处理，*/

            NonFFCount++;
            if( (0xFFu==Char) && (252u >= NonFFCount) )
            {
                /*如果在252个字符之内存在FF，解码失败*/
                State = ABNORMAL_STATE;
            }
            else
            {
                /*接受非FF字符*/
                pTgt[TgtPos]=Char;
                TgtPos++;

                if(252u == NonFFCount)
                {
                    NonFFCount=0u;
                    State = WAIT_FF_C1;
                }
                else
                {
                }
            }
            break;
        case WAIT_FF_POS:
            /*等待插入FF字符的位置*/

            if(0xFFu == Char)
            {
                /*当前字符是FF字符*/

                State = ABNORMAL_STATE;
            }
            else
            {
                /*当前字符非FF字符*/

                pTgt[TgtPos]=Char;
                TgtPos++;
                if(SrcPos == NextFFPos)
                {
                    pTgt[TgtPos]=0xffu;
                    TgtPos++;
                    State = WAIT_FF_C1;
                }
				else
				{
					; /*继续执行*/
				}
            }
            break;
        default:
            State = ABNORMAL_STATE;
            break;
        }
        if(ABNORMAL_STATE == State)
        {
            /*非法状态*/
            TgtPos=0u;
            break;
        }
        else
        {
        }
    }

    /*退出时的状态判断*/
    if((WAIT_FF_C2 == State)||(WAIT_FF_POS == State))
    {
        TgtPos = 0u;
    }
	else
	{
		; /*继续执行*/
	}
    return TgtPos;
}

/*
* 功能描述：  FFFE结构体初始化函数
* 输入参数：  UINT16 FFFEBufferSize, 用于接收一帧数据的缓冲区长度   
*             FFFE_STATE_STRU *pFFFEStatStru, FFFE状态结构体
* 返回值：    0,函数执行失败
*             1,函数执行成功
*/
UINT8 FFFEInit(FFFE_STATE_STRU *pFFFEStatStru,UINT16 FFFEBufferSize)
{
	
		UINT8 ret = 0u;
		if (NULL == pFFFEStatStru)
		{
			; /*入口参数错误*/
		} 
		else
		{
			/*FFFE状态清零复位*/
			pFFFEStatStru->RawDataRcvBufferSize = FFFEBufferSize;
			pFFFEStatStru->pRawDataRcvBuf = (UINT8*)malloc(pFFFEStatStru->RawDataRcvBufferSize * sizeof(UINT8));
			if (pFFFEStatStru->pRawDataRcvBuf == NULL)
			{
				ret = 0u;
			}
			else
			{
				pFFFEStatStru->RcvState = COM_WAIT_START_FF;
				pFFFEStatStru->GotFrame = 0u;
				pFFFEStatStru->DataCount = 0u;
				ret = 1u;
			}

		}

	return ret;
}

/*
* 功能描述：   按字符接收待解转义的数据，获得整帧FFFE报文（不含FFFE和FFFD）。
* 输入参数：   UINT8 RcvChar,      当前接收的字符
*              PORT_STATE_STRU *pFFFEStatStru,
* 输出参数：   UINT8 *pRawDataRcv,  数据接收缓冲区指针
* 返回值：     大于0,  表示收到完整帧的数据长度，并将收到的完整帧拷贝到接收缓冲区；
*              0,   未收到整帧数据； 
*/

UINT16 FFFERcv(FFFE_STATE_STRU *pFFFEStatStru,UINT8 RcvChar, UINT8 *pRawDataRcv)
{

    UINT16 ReturnVal = 0u;
    UINT16 iii = 0u;

	if ((NULL == pFFFEStatStru) || (NULL == pRawDataRcv))
	{
		; /*入参为空*/
	} 
	else
	{

		/*运行接收状态机*/
		switch(pFFFEStatStru->RcvState)
		{
		case COM_WAIT_START_FF:

			/*等待接收开始FF状态*/
			if(0xFFu != RcvChar)
			{

			}
			else
			{
				pFFFEStatStru->RcvState = COM_WAIT_START_FE;
			}
			break;
		case COM_WAIT_START_FE:

			/*等待接收开始FE状态*/
			if(0xFEu != RcvChar)
			{
				pFFFEStatStru->RcvState = COM_WAIT_START_FF;
			}
			else
			{
				pFFFEStatStru->DataCount = 0u;
				pFFFEStatStru->GotFrame = 0u;
				pFFFEStatStru->RcvState = COM_WAIT_STOP_FF;
			}            
			break;
		case COM_WAIT_STOP_FF:

			/*等待接收停止FF状态*/
			if(0xFFu == RcvChar)
			{
				pFFFEStatStru->RcvState = COM_WAIT_STOP_FD;
			}
			else
			{

				if(pFFFEStatStru->DataCount >= pFFFEStatStru->RawDataRcvBufferSize)
				{
					pFFFEStatStru->DataCount = 0u;
					pFFFEStatStru->GotFrame = 0u;
					pFFFEStatStru->RcvState = COM_WAIT_START_FF;
				}
				else
				{     
            		  pFFFEStatStru->pRawDataRcvBuf[pFFFEStatStru->DataCount] = RcvChar; 
					pFFFEStatStru->DataCount++;

				}
			}
			break;
		case COM_WAIT_STOP_FD:

			/*等待接收停止FD状态*/
			switch(RcvChar)
			{
			case 0xFFu:
				pFFFEStatStru->DataCount = 0u;
				pFFFEStatStru->GotFrame = 0u;
				pFFFEStatStru->RcvState = COM_WAIT_START_FF;                 
				break;
			case 0xFEu:
				pFFFEStatStru->DataCount = 0u;
				pFFFEStatStru->GotFrame = 0u;
				pFFFEStatStru->RcvState = COM_WAIT_STOP_FF;                 
				break;
			case 0xFDu:
				pFFFEStatStru->GotFrame = 1u;
				pFFFEStatStru->RcvState = COM_WAIT_START_FF;
				break;
			default:

				if(pFFFEStatStru->DataCount >= (pFFFEStatStru->RawDataRcvBufferSize-1u))
				{
					pFFFEStatStru->DataCount = 0u;
					pFFFEStatStru->GotFrame = 0u;
					pFFFEStatStru->RcvState = COM_WAIT_START_FF;
				}
				else
				{  
            		pFFFEStatStru->pRawDataRcvBuf[pFFFEStatStru->DataCount] = 0xFFu; 
					pFFFEStatStru->DataCount++;
					pFFFEStatStru->pRawDataRcvBuf[pFFFEStatStru->DataCount] = RcvChar; 
					pFFFEStatStru->DataCount++;
					pFFFEStatStru->RcvState = COM_WAIT_STOP_FF; 
				}
				break;
			}
			break;
		default:
			break;
		}

		/*收到完整帧*/
		if(1u == pFFFEStatStru->GotFrame)
		{
			for(iii=0u; iii<pFFFEStatStru->DataCount; iii++)
			{
				pRawDataRcv[iii] = pFFFEStatStru->pRawDataRcvBuf[iii];
			}

			ReturnVal = pFFFEStatStru->DataCount;
			pFFFEStatStru->DataCount = 0u;
			pFFFEStatStru->GotFrame = 0u;
		}
		else
		{
		}
	}
    return ReturnVal;
}

/*
* 功能描述：  FFFE状态清理函数
* 输入参数：  PORT_STATE_STRU *pFFFEStatStru, FFFE状态结构体
* 返回值：     
*/
void FFFEFree(FFFE_STATE_STRU *pFFFEStatStru)
{
	if (NULL == pFFFEStatStru)
	{
		; /*入口参数错误*/
	} 
	else
	{
		/*FFFE清理*/
		free(pFFFEStatStru->pRawDataRcvBuf);
		pFFFEStatStru->pRawDataRcvBuf = NULL;

	}

}


/*
* 功能描述： 将数据进行FFFE转义处理,加头FFFE及尾FFFD
* 输入参数： const UINT8 *pSrc    数据(无FFFE转义)
*            UINT16 SrcLen        数据(无FFFE转义)的长度
* 输出参数： UINT8 *pTgt          数据(经过FFFE转义),并添加FFFE头及FFFD尾
* 返回值：   转义后的长度   
*/
UINT16 FFFEPack(const UINT8 *pSrc, UINT8 *pTgt,UINT16 SrcLen)
{
	UINT16 PackDataLen=0u;
	
	if ((NULL == pSrc) || (NULL == pTgt))
	{
		; /*入口参数错误*/
	} 
	else
	{

		/*添加FFFE头*/
		pTgt[PackDataLen] = 0xFFu;
		PackDataLen++;
		pTgt[PackDataLen] = 0xFEu;
		PackDataLen++;

		/*数据转义*/
		PackDataLen += TranslateToFFFE(pSrc, pTgt + PackDataLen, SrcLen);

		/*添加FFFD尾*/
		pTgt[PackDataLen] = 0xFFu;
		PackDataLen++;
		pTgt[PackDataLen] = 0xFDu;
		PackDataLen++;

	}
	return PackDataLen;


}

