/**
* @file SFM_package.c
* @brief Safe Function Module:分帧协议实现
* @author GT-BU
* @date 2021.02.20
* @version V1.0
* @copyright TCT
* @par 修改日志
* <table>
* <tr><th>Date        <th>Version  <th>Author     <th>Description
* <tr><td>2021.02.01  <td>V1.0     <td>GT-BU      <td>创建初始版本
* </table>
*/
#include "SFM_package.h"
#include "CM_Memory.h"
#include "PFM_Log.h"
#include "DFM_Time.h"
/**
* @brief 分帧接收
* @param pCtrl 控制结构体
* @param type 帧类型
* @param FrameNum 帧数目
* @param FrameIndex 帧序号
* @param pFrameData 分帧数据报文指针
* @param FrameDataLen 分帧数据报文长度
* @param pRxBuf 接收缓冲区指针
* @param pRxLen 接收报文总长度
* @param RxSize 接收缓冲区大小
* @return 处理结果
* - ENUM_CM_FALSE 处理出错
* - ENUM_CM_TRUE 处理完成（收齐完整报文）
* - ENUM_CM_NULL 处理中（接收有效，但尚未收齐完整报文）
* @details 收齐完整报文后才会置位接收报文总长度，否则为0
*/
ENUM_CM_RETURN SFM_FrameSave(INOUT STRU_FrameCtrl_T *pCtrl, IN CM_UINT8 type, 
    IN CM_UINT16 FrameNum, IN CM_UINT16 FrameIndex, IN const CM_UINT8 *pFrameData, IN CM_INT32 FrameDataLen, 
    INOUT CM_UINT8 *pRxBuf, OUT CM_INT32 *pRxLen, IN CM_UINT32 RxSize)
{
    /*- 变量初始化 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
    /*- 指针防空 */
    CM_ASSERT((NULL != pRxBuf) && (NULL != pFrameData) && (NULL != pCtrl), PACKAGE_MODE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_1);
    /*- 是否收到新报文 */
    if (1u == FrameIndex)
    {
        /*- 初始化控制结构体 */
        pCtrl->type = type;
        pCtrl->FrameNum = FrameNum;
        pCtrl->FramIndex = 0u;
        pCtrl->RxLen = 0;
        /*- 接收报文总长度置0 */
        *pRxLen = 0;
    }
    else
	{
		/*- 无处理 */
	}
    /*- 检查收到的分帧帧头信息是否合法 */
    if ((type == pCtrl->type)
        && (FrameNum == pCtrl->FrameNum)
        && (FrameIndex == (pCtrl->FramIndex + 1u)))
    {
        /*- 收到的帧序号累加 */
        pCtrl->FramIndex++;

        /*- 保存本帧数据 */
        rt = CM_Memcpy((void*)(pRxBuf + pCtrl->RxLen), (CM_SIZE_T)CM_SIGNED_INT_EXP((CM_INT32)RxSize - pCtrl->RxLen), (const void*)pFrameData, (CM_SIZE_T)FrameDataLen); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
        CM_RE_ASSERT(ENUM_CM_TRUE == rt, PACKAGE_MODE, DARK_FAULT_CODE_FUN_ORDER_1, TSCP_DARK_ASSERT_2);
        pCtrl->RxLen += FrameDataLen;

        /*- 是否是最后一帧 */
        if (FrameIndex == FrameNum)
        {
            /*- 初始化控制结构体 */
            pCtrl->type = 0;
            pCtrl->FrameNum = 0;
            pCtrl->FramIndex = 0u;
            /*- 输出报文总长度 */
            *pRxLen = pCtrl->RxLen;
            /*- 返回值置ENUM_CM_TRUE */
            rt = ENUM_CM_TRUE;
        }
        else
        {
            /*- 返回值置ENUM_CM_NULL */
            rt = ENUM_CM_NULL;
        }
    }
    else
    {
    	/*- 记录丢包次数与周期*/
    	pCtrl->err_cut++;
    	pCtrl->err_cyc = g_MSCP_BirthCount;
    	MSCP_LOG_MSG("SFM_FrameSave error:\n type = %d, pCtrl->type = %d, FrameNum = %d, pCtrl->FrameNum = %d, FrameIndex = %d, pCtrl->FramIndex = %d\n",type,pCtrl->type,FrameNum,pCtrl->FrameNum,FrameIndex,pCtrl->FramIndex);
    	(void)CFM_DarkLog_Multiple(DARK_LOG_HEX, TSCP_DARK_SFM_2OO2FRAME,8u,
										sizeof(CM_UINT16),pCtrl->err_cut,
										sizeof(CM_UINT32),pCtrl->err_cyc,
    									sizeof(CM_UINT8),type,
    									sizeof(CM_UINT8),pCtrl->type,
    									sizeof(CM_UINT16),FrameNum,
										sizeof(CM_UINT16),pCtrl->FrameNum,
										sizeof(CM_UINT16),FrameIndex,
										sizeof(CM_UINT16),pCtrl->FramIndex);
    }
    /*- 输出返回值*/
    return rt;
}
/**
* @brief 2X分帧接收
* @param pCtrl 控制结构体
* @param type 帧类型
* @param FrameNum 帧数目
* @param FrameIndex 帧序号
* @param pFrameData 分帧数据报文指针
* @param FrameDataLen 分帧数据报文长度
* @param pRxBuf 接收缓冲区指针
* @param pRxLen 接收报文总长度
* @param RxSize 接收缓冲区大小
* @return 处理结果
* - ENUM_CM_FALSE 处理出错
* - ENUM_CM_TRUE 处理完成（收齐完整报文）
* - ENUM_CM_NULL 处理中（接收有效，但尚未收齐完整报文）
* @details 收齐完整报文后才会置位接收报文总长度，否则为0
*/
ENUM_CM_RETURN SFM_2X_FrameSave(INOUT STRU_FrameCtrl_T *pCtrl, IN CM_UINT8 type,
    IN CM_UINT16 FrameNum, IN CM_UINT16 FrameIndex, IN const CM_UINT8 *pFrameData, IN CM_INT32 FrameDataLen,
    INOUT CM_UINT8 *pRxBuf, OUT CM_INT32 *pRxLen, IN CM_UINT32 RxSize)
{
    /*- 变量初始化 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
    /*- 指针防空 */
    CM_ASSERT((NULL != pRxBuf) && (NULL != pFrameData) && (NULL != pCtrl), PACKAGE_MODE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_1);
    /*- 是否收到新报文 */
    if (1u == FrameIndex)
    {
        /*- 初始化控制结构体 */
        pCtrl->type = type;
        pCtrl->FrameNum = FrameNum;
        pCtrl->FramIndex = 0u;
        pCtrl->RxLen = 0;
        /*- 接收报文总长度置0 */
        *pRxLen = 0;
    }
    else
	{
		/*- 无处理 */
	}
    /*- 检查收到的分帧帧头信息是否合法 */
    if ((type == pCtrl->type)
        && (FrameNum == pCtrl->FrameNum)
        && (FrameIndex == (pCtrl->FramIndex + 1u)))
    {
        /*- 收到的帧序号累加 */
        pCtrl->FramIndex++;

        /*- 保存本帧数据 */
        rt = CM_Memcpy((void*)(g_2x2oo2_Frame_TempBuf + pCtrl->RxLen), (CM_SIZE_T)CM_SIGNED_INT_EXP((CM_INT32)RxSize - pCtrl->RxLen), (const void*)pFrameData, (CM_SIZE_T)FrameDataLen); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
        CM_RE_ASSERT(ENUM_CM_TRUE == rt, PACKAGE_MODE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_2);
        pCtrl->RxLen += FrameDataLen;

        /*- 是否是最后一帧 */
        if (FrameIndex == FrameNum)
        {
            /*- 输出报文总长度 */
            *pRxLen = pCtrl->RxLen;
            rt = CM_Memcpy(pRxBuf,RxSize,g_2x2oo2_Frame_TempBuf,pCtrl->RxLen);
            CM_RE_ASSERT(ENUM_CM_TRUE == rt, PACKAGE_MODE, DARK_FAULT_CODE_FUN_ORDER_3, TSCP_DARK_ASSERT_3);
            /*- 返回值置ENUM_CM_TRUE */
            rt = ENUM_CM_TRUE;
        }
        else
        {
            /*- 返回值置ENUM_CM_NULL */
            rt = ENUM_CM_NULL;
        }
    }
    else
    {
    	MSCP_LOG_MSG("SFM_2X_FrameSave error:\n type = %d, pCtrl->type = %d, FrameNum = %d, pCtrl->FrameNum = %d, FrameIndex = %d, pCtrl->FramIndex = %d\n",type,pCtrl->type,FrameNum,pCtrl->FrameNum,FrameIndex,pCtrl->FramIndex);
        /*- 出错后复位接收控制 */
        pCtrl->type = 0u;
    	(void)CFM_DarkLog_Multiple(DARK_LOG_HEX, TSCP_DARK_SFM_2X2FRAME,6u,
    									sizeof(CM_UINT8),type,
    									sizeof(CM_UINT8),pCtrl->type,
    									sizeof(CM_UINT16),FrameNum,
										sizeof(CM_UINT16),pCtrl->FrameNum,
										sizeof(CM_UINT16),FrameIndex,
										sizeof(CM_UINT16),pCtrl->FramIndex);
    }
    /*- 输出返回值*/
    return rt;
}
/**
* @brief 应用分帧接收
* @param pCtrl 控制结构体 取值范围：非空
* @param FrameNum 帧数目 取值范围：0~0xFFFF
* @param FrameIndex 帧序号  取值范围：0~0xFFFF
* @param pFrameData 分帧数据报文指针 取值范围：非空
* @param FrameDataLen 分帧数据报文长度 取值范围：0~0x7FFFFFFFF
* @param pRxBuf 接收缓冲区指针 取值范围：非空
* @param pRxLen 接收报文总长度 取值范围：非空
* @param RxSize 接收缓冲区大小 取值范围：0~0xFFFFFFFFF
* @return 处理结果
* - ENUM_CM_FALSE 处理出错
* - ENUM_CM_TRUE 处理完成（收齐完整报文）
* - ENUM_CM_NULL 处理中（接收有效，但尚未收齐完整报文）
* @details 收齐完整报文后才会置位接收报文总长度，否则为0
*/
ENUM_CM_RETURN SFM_FrameSave_App(INOUT STRU_FrameCtrl_T *pCtrl, 
    IN CM_UINT16 FrameNum, IN CM_UINT16 FrameIndex, IN const CM_UINT8 *pFrameData, IN CM_INT32 FrameDataLen, 
    INOUT CM_UINT8 *pRxBuf, OUT CM_INT32 *pRxLen, IN CM_UINT32 RxSize)
{
    /*- 变量初始化 */
    ENUM_CM_RETURN rt = ENUM_CM_FALSE; /* 函数返回值 */
    /*- 指针防空 */
    CM_ASSERT((NULL != pRxBuf) && (NULL != pFrameData) && (NULL != pCtrl), PACKAGE_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
    /*- 是否收到新报文 */
    if (1u == FrameIndex)
    {
        /*- 初始化控制结构体 */
        pCtrl->FrameNum = FrameNum;
        pCtrl->FramIndex = 0u;
        pCtrl->RxLen = 0;
        /*- 接收报文总长度置0 */
        *pRxLen = 0;
    }
    else
	{
		/*- 无处理 */
	}
    /*- 检查收到的分帧帧头信息是否合法 */
    if ((FrameNum == pCtrl->FrameNum)
        && (FrameIndex == (pCtrl->FramIndex + 1u)))
    {
        /*- 收到的帧序号累加 */
        pCtrl->FramIndex++;

        /*- 保存本帧数据 */
        rt = CM_Memcpy((void*)(pRxBuf + pCtrl->RxLen), (CM_SIZE_T)CM_SIGNED_INT_EXP((CM_INT32)RxSize - pCtrl->RxLen), (const void*)pFrameData, (CM_SIZE_T)FrameDataLen); /* parasoft-suppress MISRA2004-17_1 MISRA2004-17_4 "指针运算提高代码执行效率" */
        CM_ASSERT(ENUM_CM_TRUE == rt, PACKAGE_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_2);
        pCtrl->RxLen += FrameDataLen;

        /*- 是否是最后一帧 */
        if (FrameIndex == FrameNum)
        {
            /*- 输出报文总长度 */
            *pRxLen = pCtrl->RxLen;
            /*- 返回值置ENUM_CM_TRUE */
            rt = ENUM_CM_TRUE;
        }
        else
        {
            /*- 返回值置ENUM_CM_NULL */
            rt = ENUM_CM_NULL;
        }
    }
    else
    {
        /*- 出错后复位接收控制 */
        pCtrl->type = 0u;
    }
    /*- 输出返回值*/
    return rt;
}
