/******************************************************************************

版权所有 (C), 2013-2023, 科大智能电气有限公司

******************************************************************************
文 件 名   : gb101.c
版 本 号   : V1.0
生成日期   : 2022年03月23日
最近修改   :
功能描述   : 101规约实现主体
函数列表   :
修改历史   :
1.日    期   : 2022年03月23日
修改内容   : 创建文件
******************************************************************************/
/*************************************文件包含*********************************/
#include "gb101.h"

/***************************************static函数声明*******************************/
static void GB101_SendShortX(CS10xHandle_t pstSelf, unsigned char ucPRM, unsigned char ucFC);
static unsigned char   GB101_SearchOneFrame(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen, unsigned short *pusFramePos);
static void GB101_DecodeOneFrame(CS10xHandle_t pstSelf, unsigned char *pucBuf);
/*************************************外部接口函数*****************************/
/**
* @brief    规约使用前初始化
* @param[in]  pstSelf-函数实体指针
* @param[in]  cb-发送函数指针
* @param[in]  arg-用户数据指针
* @param[in]  enType-规约类型 主从
* @param[out] 无
* @return     规约实体指针
*/
void CS10x_101Init(CS10xHandle_t pstSelf, CS10x_SendCb pcb, void *arg, CS10x_Type enType)
{
	pstSelf->eCS10x_Type     = enType; //主站从站
	pstSelf->pfnSendCb           = pcb;
	pstSelf->pUsrData         = arg;
	pstSelf->pfnDecodeProcess    = GB101_DecodeProcess;
	pstSelf->pfnEncodeFrame      = GB101_EncodeFrame;
	pstSelf->pfnEncodeOther      = GB101_EncodeOther;
	pstSelf->pfnTimerManager     = GB101_TimerOut;
	/*默认初始化参数*/
	pstSelf->usYcType         = YC_TYPE_ME_NC;
	pstSelf->usYxType         = YX_TYPE_M_SP;
	pstSelf->usYkType         = YK_TYPE_C_SC;
	pstSelf->usDdType         = DD_TYPE_IT_NB;
	pstSelf->usAsduPublicAddr = 1;
	/*应用参数*/
	pstSelf->stAppParameters.iSzOfLinkAddr = 2;
	pstSelf->stAppParameters.iSzOfTypeId   = 1;
	pstSelf->stAppParameters.iSzOfVSQ      = 1;
	pstSelf->stAppParameters.iSzOfCOT      = 2;
	pstSelf->stAppParameters.iSzOfCA       = 2;
	pstSelf->stAppParameters.iSzOfIOA      = 2;
	pstSelf->stAppParameters.iLinkAddr       = 1;
	pstSelf->stAppParameters.iPublicAddr     = 1;
	/*总招对时时间*/
	pstSelf->uiSummon_Gap = 300000; /*300秒*/
	pstSelf->uiSyn_Gap    = 300000; /*300秒*/
	pstSelf->uiSend_Gap   = 100;    /*100ms*/
	pstSelf->uiHeart_Gap  = 90000;  /*90秒*/
	pstSelf->uiESummon_Gap = 60000; /*60秒*/
	/*重发参数*/
	pstSelf->usReSend_Gap = 5000; /*1秒*/
	pstSelf->ucReSend_Num = 5;
	pstSelf->bSimpleInit = 1;   // 简单初始化
	pstSelf->ucFileAckType = 0; // 文件传输要求确认
	pstSelf->usFaultEnable = 1; //故障事件使能
	pstSelf->ucSenSoeEa = 1; //发送SOE使能
	pstSelf->ucSenCosEa = 1; //发送COS使能
	pstSelf->ucYKEndFrame = 1; //遥控结束帧投入
	pstSelf->ucReadFileVSQ = 0; //读文件数据传输VSQ状态值
	pstSelf->bDir = 1;
	pstSelf->ucPreSetContType = 0; /* 默认为正常参数预置流程*/
#ifdef IEC_DEBUG_MSG
	IEC_PRINT("Create IEC101 %s\n", enType == CS101_TYPE_M ? "主站" : "从站");
#endif
	return;
}

/*************************************内部调用函数*****************************/
/**
* @brief    101规约数据帧处理
* @param[in]  pstSelf-规约实体指针
* @param[in]  pucBuf-报文数据指针
* @param[in]  usLen-报文长度
* @param[out] 无
* @return     规约实体指针
*/
char GB101_DecodeProcess(CS10xHandle_t pstSelf, unsigned char *pucBuf, unsigned short usLen)
{
	unsigned short usFramePos  = 0;//一条报文中含有多帧101时，表示每帧起始在报文中起始位置
	unsigned short usSearchLen = 0;//本次查找报文的长度(包括错误帧)

	// to do :proc ASDUs 拆分多帧并解析
	do
	{
		if(GB101_SearchOneFrame(pstSelf, pucBuf + usFramePos, usLen - usFramePos, &usSearchLen)) //查找单帧
		{
			break;
		}

		GB101_DecodeOneFrame(pstSelf, pstSelf->stPubBuf.pBuf);//解析单帧
		usFramePos += usSearchLen;
	} while(usFramePos < usLen);          //越界判断

	return 0;
}

/**
* @brief    101规约查找单帧
* @param[in]  pstSelf-规约实体指针
* @param[in]  pucFramePt-当前帧报文数据指针
* @param[in]  usLastLen-多帧报文剩余长度
* @param[out] pusSearchLen-本次查找报文的长度(包括错误帧)
* @return     0 正常查找      1 异常越界
*/
static unsigned char GB101_SearchOneFrame(CS10xHandle_t pstSelf, unsigned char *pucFramePt, unsigned short usLastLen, unsigned short *pusSearchLen)
{
	unsigned char  ucRet              = 0;//返回判断0 正常查找   1 异常越界
	unsigned char  ucFlag             = 0;//寻找单帧成功标志 0 成功   1 失败
	unsigned char  ucSum              = 0; //校验码
	unsigned char  ucCS_Pos           = 0; //长帧校验位下标
	unsigned short usAddr             = 0; //链路地址
	unsigned short usSearchLen        = 0;//本次查找报文的长度(包括错误帧)
	VFrame10_S stFrame10_S = {0};//101短帧格式(单字节地址)
	VFrame10   stFrame10   = {0};  //101短帧格式(双字节地址)
	VFrame68   stFrame68   = {0};  //101长帧格式

	do
	{
		if(pucFramePt[0] == START_CODE_101_SHORT)  // 101短帧  短帧起始都一样
		{
			if(pstSelf->stAppParameters.iSzOfLinkAddr == 1)
			{
				if(usSearchLen + SHORT_LEN_S > usLastLen)  //越界判断
				{
					ucRet = 1;
					break;
				}

				stFrame10_S.ucControl = pucFramePt[1];//控制域
				stFrame10_S.ucAddr    = pucFramePt[2];//地址域
				stFrame10_S.ucCS      = pucFramePt[3];//校验和
				stFrame10_S.ucTail    = pucFramePt[4];//结束符
				ucSum = checksum_8(&stFrame10_S.ucControl, 2);

				if((stFrame10_S.ucCS == ucSum) && (stFrame10_S.ucTail == TAIL_CODE_101) && ((stFrame10_S.ucAddr == pstSelf->stAppParameters.iLinkAddr) || (stFrame10_S.ucAddr == 255)))
				{
					memcpy(pstSelf->stPubBuf.pBuf, pucFramePt, SHORT_LEN_S);//拷贝当前帧到公共缓存待解析
					pstSelf->stPubBuf.usWritePtr = SHORT_LEN_S;
					usSearchLen += SHORT_LEN_S;
					ucFlag = 1;
					break;//当前帧格式正确结束遍历，外层解析当前帧
				}
				else
				{
					usSearchLen += 1;
					pucFramePt += 1;

					if(usSearchLen + SHORT_LEN > usLastLen)
					{
						ucRet = 1;
						break;
					}
				}
			}
			else
			{
				if(usSearchLen + SHORT_LEN > usLastLen)  //越界判断
				{
					ucRet = 1;
					break;
				}

				stFrame10.ucControl = pucFramePt[1];//控制域
				stFrame10.ucAddr_L  = pucFramePt[2];//地址域
				stFrame10.ucAddr_H  = pucFramePt[3];//地址域
				stFrame10.ucCS      = pucFramePt[4];//校验和
				stFrame10.ucTail    = pucFramePt[5];//结束符
				ucSum = checksum_8(&stFrame10.ucControl, 3);
				usAddr = stFrame10.ucAddr_H;
				usAddr = ((usAddr << 8) & 0xff00) + stFrame10.ucAddr_L;

				if((stFrame10.ucCS == ucSum) && (stFrame10.ucTail == TAIL_CODE_101) && ((usAddr == pstSelf->stAppParameters.iLinkAddr) || (usAddr == 65535)))
				{
					memcpy(pstSelf->stPubBuf.pBuf, pucFramePt, SHORT_LEN);//拷贝当前帧到公共缓存待解析
					pstSelf->stPubBuf.usWritePtr = SHORT_LEN;
					usSearchLen += SHORT_LEN;
					ucFlag = 1;
					break;//当前帧格式正确结束遍历，外层解析当前帧
				}
				else
				{
					usSearchLen += 1;
					pucFramePt += 1;

					if(usSearchLen + SHORT_LEN > usLastLen)
					{
						ucRet = 1;
						break;
					}
				}
			}
		}
		else if(pucFramePt[0] == START_CODE_101_LONG)  // 101长帧
		{
			stFrame68.ucLength1 = pucFramePt[1];
			stFrame68.ucLength2 = pucFramePt[2];
			stFrame68.ucStart2  = pucFramePt[3];
			stFrame68.ucControl = pucFramePt[4];
			memcpy(stFrame68.ucaData, &pucFramePt[5], stFrame68.ucLength1 - 1 + 2); //不包括控制域,包括校验、结束子符

			if((stFrame68.ucLength1 == stFrame68.ucLength2) && (stFrame68.ucLength1 < 249) && (stFrame68.ucStart2 == START_CODE_101_LONG))
			{
				if(usSearchLen + stFrame68.ucLength1 + HEAD_TAIL_LEN > usLastLen)  //越界判断
				{
					ucRet = 1;
					break;
				}

				if(pstSelf->stAppParameters.iSzOfLinkAddr == 1)
				{
					ucSum = checksum_8(&stFrame68.ucControl, stFrame68.ucLength1);
					ucCS_Pos = stFrame68.ucLength1 - 1;

					if((stFrame68.ucaData[ucCS_Pos] == ucSum) && (stFrame68.ucaData[ucCS_Pos + 1] == TAIL_CODE_101) && ((stFrame68.ucaData[0] == pstSelf->stAppParameters.iLinkAddr) || (stFrame68.ucaData[0] == 255)))
					{
						pstSelf->stPubBuf.usWritePtr = stFrame68.ucLength1 + HEAD_TAIL_LEN;
						memcpy(pstSelf->stPubBuf.pBuf, pucFramePt, pstSelf->stPubBuf.usWritePtr);//拷贝当前帧到公共缓存待解析
						usSearchLen += pstSelf->stPubBuf.usWritePtr;
						ucFlag = 1;
						break;//当前帧格式正确结束遍历，外层解析当前帧
					}
					else
					{
						usSearchLen += 1;
						pucFramePt += 1;
					}
				}
				else
				{
					ucSum = checksum_8(&stFrame68.ucControl, stFrame68.ucLength1);
					usAddr = stFrame68.ucaData[1];
					usAddr = ((usAddr << 8) & 0xff00) + stFrame68.ucaData[0];
					ucCS_Pos = stFrame68.ucLength1 - 1;

					if((stFrame68.ucaData[ucCS_Pos] == ucSum) && (stFrame68.ucaData[ucCS_Pos + 1] == TAIL_CODE_101) && ((usAddr == pstSelf->stAppParameters.iLinkAddr) || (usAddr == 65535)))
					{
						pstSelf->stPubBuf.usWritePtr = stFrame68.ucLength1 + HEAD_TAIL_LEN;
						memcpy(pstSelf->stPubBuf.pBuf, pucFramePt, pstSelf->stPubBuf.usWritePtr);//拷贝当前帧到公共缓存待解析
						usSearchLen += pstSelf->stPubBuf.usWritePtr;
						ucFlag = 1;
						break;//当前帧格式正确结束遍历，外层解析当前帧
					}
					else
					{
						usSearchLen += 1;
						pucFramePt += 1;
					}
				}
			}
			else
			{
				usSearchLen += 1;
				pucFramePt += 1;
			}
		}
		else
		{
			usSearchLen += 1;
			pucFramePt += 1;
		}
	} while(usSearchLen < usLastLen);          //越界判断

	if(ucFlag != 1)
	{
		ucRet = 1;
	}

	*pusSearchLen = usSearchLen;//参数返回本次查找长度
	return ucRet;
}

/**
* @brief    101规约解析单帧
* @param[in]  pstSelf-规约实体指针
* @param[in]  pucBuf-报文数据指针
* @param[out] 无
* @return     无
*/
static void GB101_DecodeOneFrame(CS10xHandle_t pstSelf, unsigned char *pucBuf)
{
	if(pucBuf[0] == START_CODE_101_SHORT) // 101短帧
	{
		GB101_ShortFrame(pstSelf, pucBuf);
	}
	else if(pucBuf[0] == START_CODE_101_LONG)  // 101长帧
	{
		GB101_LongFrame(pstSelf, pucBuf);
	}
}

/**
* @brief    101规约收到的长帧解析处理接口函数
* @param[in]  pstSelf-规约实体指针
pucFrameStart-当前帧首指针
* @param[out] 无
* @return     无
*/
void GB101_LongFrame(CS10xHandle_t pstSelf, unsigned char *pucFrameStart)
{
	unsigned char ucLen = 0; //控制域加地址域的长度
	VIec101Frame *pstRcvFrame = (VIec101Frame *)pucFrameStart;

	if(pstSelf->stAppParameters.iSzOfLinkAddr > 2)
	{
		return;
	}

	/* 长帧直接认为初始化完成，保证现场数据正常上送
	*  目前南瑞等主站会存在初始化过程发送总招或者对
	*  时等相关数据，可能导致流程不正常 */
	pstSelf->ucInitStatus = 1;
	ucLen += pstSelf->stAppParameters.iSzOfLinkAddr;
	ucLen++;
	//切换到ASDU域起始指针
	pucFrameStart += ucLen + HEAD_LEN; /*规约头报文长度*/
	//长帧也认为是数据确认
	DoAckFrame(pstSelf);
	pstSelf->usResend_Ncn = 0;
	pstSelf->uiResend_Tcn = 0;
	pstSelf->uiHeart_Tcn = 0;
	SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0); // 101规约长帧都要回复确认帧
	/*处理ASDU元素*/
	DecodeAsduMember(pstSelf, pucFrameStart, pstRcvFrame->stFrame68.ucLength1 - ucLen);
	/*处理ASDU信息体*/
	DecodeAsduInfoObj(pstSelf);
	return;
}

/**
* @brief    101规约短帧解析处理接口函数
* @param[in]  pstSelf-规约实体指针
pucFrameStart-当前帧首指针
* @param[out] 无
* @return     无
*/
void GB101_ShortFrame(CS10xHandle_t pstSelf, unsigned char *pucFrameStart)
{
	CONTROL101 unControl;//控制域联合体
	VIec101Frame *pstRcvFrame = (VIec101Frame *)pucFrameStart;
	pstSelf->uiHeart_Tcn = 0;
	unControl.control  = pstRcvFrame->stFrame10.ucControl;

	switch(unControl.bits_down.FC)  //根据功能码判断
	{
		case RESET_LINK:                             //收到复位链路帧  及确认帧   两个功能码一样需要从PRM位进行区分
			if(unControl.bits_down.PRM == PRM_MASTER)  //启动站发来的帧是复位链路帧
			{
				pstSelf->ucRxLinkResetFlag = 1;
				pstSelf->ucSelf_FCB = 0; // 收到复位链路帧后FCB位清0
			}
			else //从动站发来的是确认帧
			{
				pstSelf->ucRxAckFlag = 1;
				pstSelf->usResend_Ncn = 0;
				pstSelf->uiResend_Tcn = 0;
				//          CheckUpdate_DiturbYcEvent(pstSelf);
				//          CheckUpdate_SoeEvent(pstSelf); //更新SOE及故障事件已发送指针
				DoAckFrame(pstSelf);

				if(pstSelf->pfnAckFrameNotification)
				{
					pstSelf->pfnAckFrameNotification();
				}
			}

			break;

		case TEST_LINK:

			/*初始化链路完成才可以相应测试帧*/
			if(pstSelf->ucInitStatus == 1)
			{
				SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0); //发送确认帧
			}

			break;

		case NONE_DATA:
			break;

		case REQUEST_LINK: //收到请求链路帧
			pstSelf->ucRxLinkRequestFlag = 1;
			pstSelf->ucInitStatus = 0;
			break;

		case LINKSTATUS: //收到链路状态帧
			pstSelf->ucRxLinkStatusFlag = 1;
			break;

		default:
			break;
	}

	return;
}

/**
* @brief    101规约组建ASDU域接口函数
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     0-成功 -1-失败
*/
char GB101_EncodeFrame(CS10xHandle_t pstSelf)
{
#define MAX_FILE_NONE_ACK_SIEZ  32 /* 最大不带确认帧个数 按照100ms一帧， 32帧相当于3200ms 和主站正反向隔离时间相当 */
	pstSelf->stSendBuf.usReadPtr = 0;
	pstSelf->stSendBuf.usWritePtr = 0;
	VIec101Frame * pstFrame = (VIec101Frame *)pstSelf->stSendBuf.pBuf;
	pstSelf->stSendBuf.usWritePtr += GB101_EncodeFrameHead(pstSelf, pstFrame);
	pstSelf->stSendBuf.usWritePtr += GB10x_EncodeAsdu(pstSelf, (unsigned char *)pstFrame + pstSelf->stSendBuf.usWritePtr);
	GB101_EncodeFrameTail(pstSelf, pstFrame);

	/* 文件传输不带确认帧时，且无确认不超过最大帧时，可以继续发送后续帧*/
	if((pstSelf->ucFileAckType == 1 && pstSelf->ucFileTransFrame == 1 &&
	   pstSelf->usFileNoneAckNum < MAX_FILE_NONE_ACK_SIEZ))
	{
		pstSelf->ucFileTransFrame = 0;
	}
	else
	{
		pstSelf->uiResend_Tcn = pstSelf->usReSend_Gap; // 重发超时计数赋值
	}

	return 0;
}

/**
* @brief    101规约组建短帧域接口函数
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     0-成功 -1-失败
*/
char GB101_EncodeOther(CS10xHandle_t pstSelf)
{
	switch(pstSelf->byTaskFlagId)
	{
		case TSKID_Ack:        //应答帧
			GB101_SendAck(pstSelf);
			break;

		case TSKID_ResetLink:  //发送复位链路
			GB101_SendResetLink(pstSelf);
			break;

		case TSKID_RequestLink://发送请求链路状态
			GB101_SendRequestLink(pstSelf);
			break;

		case TSKID_MResponse:  //响应请求链路状态
			GB101_SendLinkStatus(pstSelf);
			break;

		case TSKID_HeartBeat:  //短帧心跳帧
			GB101_SendTestLink(pstSelf);
			break;
	}

	return 0;
}

/**
* @brief    101规约定时处理函数
* @param[in]  pstSelf-规约实体指针
* @param[in]  usGap-间隔时间ms
* @param[out] 无
* @return     无
*/
void GB101_TimerOut(CS10xHandle_t pstSelf, unsigned short usGap)
{
	GB101_Heart(pstSelf, usGap);
	GB101_Resend(pstSelf, usGap);
	GB101_Link_Init(pstSelf, usGap);
	return;
}

/**
* @brief    101规约长帧重发处理函数
* @param[in]  pstSelf-规约实体指针
* @param[in]  usGap-间隔时间ms
* @param[out] 无
* @return     无
*/
void GB101_Resend(CS10xHandle_t pstSelf, unsigned short usGap)
{
	/* 仅链路正常时需要进行数据重发*/
	if(pstSelf->ucInitStatus == 1 && pstSelf->uiResend_Tcn >= usGap)
	{
		pstSelf->uiResend_Tcn -= usGap;

		if(pstSelf->uiResend_Tcn < usGap)
		{
			pstSelf->uiResend_Tcn = 0;

			if(pstSelf->usResend_Ncn < pstSelf->ucReSend_Num)  //重发次数未到最大限度
			{
				SetSendTask(pstSelf, TSKID_ReSend, TSK_PARM_USACT, 0);
				pstSelf->usResend_Ncn++;
				pstSelf->uiResend_Tcn = pstSelf->usReSend_Gap; //重发超时计数赋值
			}
			else
			{
				pstSelf->usResend_Ncn = 0;
				//重新启动链路
				ClearAllTaskflgs(pstSelf);
			}
		}
	}
	else
	{
		pstSelf->uiResend_Tcn = 0;
	}

	return;
}


/**
* @brief    101规约心跳帧 非定时，无数据持续时间超时才发送
* @param[in]  pstSelf-规约实体指针
* @param[in]  usGap-间隔时间ms
* @param[out] 无
* @return     无
*/
void GB101_Heart(CS10xHandle_t pstSelf, unsigned short usGap)
{
	if(pstSelf->ucInitStatus && pstSelf->eCS10x_Type == CS101_TYPE_M)  //链路初始化完成
	{
		pstSelf->uiHeart_Tcn += usGap;

		if(pstSelf->uiHeart_Tcn >= pstSelf->uiHeart_Gap)  //到心跳发送时间
		{
			pstSelf->uiHeart_Tcn = 0;
			SetSendTask(pstSelf, TSKID_HeartBeat, TSK_PARM_USACT, 0);

			if(pstSelf->usReSend_Gap * pstSelf->ucReSend_Num < pstSelf->uiHeart_Gap)  //参数保护 重发时间一定小于心跳时间
			{
				pstSelf->uiResend_Tcn = pstSelf->usReSend_Gap; //重发超时计数赋值
				pstSelf->ucHeart_Resend_Flag = 1;
			}
		}

		if(pstSelf->ucHeart_Resend_Flag)
		{
			//心跳重发处理
			if(pstSelf->uiResend_Tcn >= usGap)  //与长帧重发共用标志
			{
				pstSelf->uiResend_Tcn -= usGap;

				if(pstSelf->uiResend_Tcn < usGap)
				{
					pstSelf->uiResend_Tcn = 0;

					if(pstSelf->usResend_Ncn < pstSelf->ucReSend_Num)  //重发次数未到最大限度
					{
						SetSendTask(pstSelf, TSKID_HeartBeat, TSK_PARM_USACT, 0);
						pstSelf->usResend_Ncn++;
						pstSelf->uiResend_Tcn = pstSelf->usReSend_Gap; //重发超时计数赋值
					}
					else //超过最大次数
					{
						pstSelf->usResend_Ncn = 0;
						pstSelf->ucHeart_Resend_Flag = 0;
						//重新启动链路
						ClearAllTaskflgs(pstSelf);
					}
				}
			}
			else //收到确认
			{
				pstSelf->uiResend_Tcn = 0;
				pstSelf->ucHeart_Resend_Flag = 0;
			}
		}
	}
	else
	{
		pstSelf->uiHeart_Tcn = 0;
		pstSelf->ucHeart_Resend_Flag = 0;
	}

	return;
}

/**
* @brief    101规约握手流程接口函数 定时调用
* @param[in]  pstSelf-规约实体指针
* @param[in]  usGap-间隔时间ms
* @param[out] 无
* @return     无
*/
void GB101_Link_Init(CS10xHandle_t pstSelf, unsigned short usGap)
{
	if(pstSelf->ucInitStatus)  //链路初始化完成
	{
		pstSelf->uiInit_Tcn = 0;
		pstSelf->uiInit_Resend_Ncn = 0;
		pstSelf->ucRxLinkStatusFlag = 0;
		pstSelf->ucRxLinkRequestFlag = 0;
		pstSelf->ucRxAckFlag = 0;
		pstSelf->ucRxLinkResetFlag = 0;
		pstSelf->ucRxInitFinishFlag = 0;
		pstSelf->ucInitStep = 0;
		return;
	}

	//间隔时间计数
	if(pstSelf->uiInit_Tcn >= usGap)
	{
		pstSelf->uiInit_Tcn -= usGap;
	}
	else
	{
		pstSelf->uiInit_Tcn = 0;
	}

	if(pstSelf->eCS10x_Type == CS101_TYPE_M)  //作为主站端时主动发送握手帧
	{
		//作为主站的握手流程
		switch(pstSelf->ucInitStep)
		{
			case 0: //发送请求链路
				if(pstSelf->uiInit_Resend_Ncn >= RESENDCNT_MAX)
				{
					pstSelf->ucInitStep = 0xff; //握手异常
				}
				else
				{
					SetSendTask(pstSelf, TSKID_RequestLink, TSK_PARM_USACT, 0);
					pstSelf->ucRxLinkStatusFlag = 0;
					pstSelf->ucInitStatus = 0;
					pstSelf->uiInit_Tcn = TIMEOUT;
					pstSelf->uiInit_Resend_Ncn++;
					pstSelf->ucInitStep++;
				}

				break;

			case 1: //等待请求链路回复帧
				if(pstSelf->uiInit_Tcn)
				{
					if(pstSelf->ucRxLinkStatusFlag)  //收到请求链路响应帧
					{
						pstSelf->ucRxLinkStatusFlag = 0;
						pstSelf->uiInit_Tcn = 0;
						pstSelf->uiInit_Resend_Ncn = 0;
						pstSelf->ucInitStep++;
					}
				}
				else
				{
					pstSelf->ucInitStep--;
				}

				break;

			case 2: //发送复位链路帧
				if(pstSelf->uiInit_Resend_Ncn >= RESENDCNT_MAX)
				{
					pstSelf->ucInitStep = 0xff; //握手异常
				}
				else
				{
					SetSendTask(pstSelf, TSKID_ResetLink, TSK_PARM_USACT, 0); //发送复位链路帧
					pstSelf->ucRxAckFlag = 0;
					pstSelf->ucRxLinkRequestFlag = 0;
					pstSelf->uiInit_Tcn = TIMEOUT;
					pstSelf->uiInit_Resend_Ncn++;
					pstSelf->ucInitStep++;
				}

				break;

			case 3: //等待复位链路确认帧
				if(pstSelf->uiInit_Tcn)
				{
					if(pstSelf->ucRxAckFlag)  //收到确认帧
					{
						pstSelf->ucRxAckFlag = 0;
						pstSelf->uiInit_Tcn = WAITTIME_101;
						pstSelf->uiInit_Resend_Ncn = 0;

						if(pstSelf->bSimpleInit)  //简单初始化
						{
							pstSelf->ucInitStep = 6; //直接到初始化完成等待中去
						}
						else
						{
							pstSelf->ucInitStep++;
							// pstSelf->ucRxLinkRequestFlag = 0;
						}
					}
				}
				else
				{
					pstSelf->ucInitStep--;
				}

				break;

			case 4: //等待从站发出的链路状态请求帧
				if(pstSelf->uiInit_Tcn)
				{
					if(pstSelf->ucRxLinkRequestFlag)  //收到从站的链路状态请求帧
					{
						pstSelf->ucRxLinkRequestFlag = 0;
						pstSelf->ucRxLinkResetFlag = 0;
						SetSendTask(pstSelf, TSKID_MResponse, TSK_PARM_USACT, 0); //发送请求链路状态响应帧
						pstSelf->uiInit_Tcn = WAITTIME_101;
						pstSelf->uiInit_Resend_Ncn = 0;
						pstSelf->ucInitStep++;
					}
				}
				else
				{
					pstSelf->ucInitStep = 0xff;
				}

				break;

			case 5: //等待从站发出的复位链路帧
				if(pstSelf->uiInit_Tcn)
				{
					if(pstSelf->ucRxLinkResetFlag)  //收到从站的复位链路帧
					{
						pstSelf->ucRxLinkResetFlag = 0;
						pstSelf->ucRxInitFinishFlag = 0;
						SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0); //发送确认帧
						pstSelf->uiInit_Tcn = WAITTIME_101;
						pstSelf->uiInit_Resend_Ncn = 0;
						pstSelf->ucInitStep++;
					}
				}
				else
				{
					pstSelf->ucInitStep = 0xff;
				}

				break;

			case 6: //等待从站发出的初始化完成帧
				if(pstSelf->uiInit_Tcn)
				{
					// if(pstSelf->ucRxInitFinishFlag) //收到从站的初始化完成报文
					// {
					//  pstSelf->ucInitStatus = 1; //初始化结束
					//  pstSelf->uiInit_Tcn = 0;
					//  pstSelf->uiInit_Resend_Ncn = 0;
					//  pstSelf->ucRxLinkStatusFlag = 0;
					//  pstSelf->ucRxLinkRequestFlag = 0;
					//  pstSelf->ucRxAckFlag = 0;
					//  pstSelf->ucRxLinkResetFlag = 0;
					//  pstSelf->ucRxInitFinishFlag = 0;
					// }
				}
				else
				{
					pstSelf->ucInitStep = 0xff;
				}

				break;

			case 0xff:
			default:
				pstSelf->uiInit_Tcn = 0;
				pstSelf->uiInit_Resend_Ncn = 0;
				pstSelf->ucRxLinkStatusFlag = 0;
				pstSelf->ucRxLinkRequestFlag = 0;
				pstSelf->ucRxAckFlag = 0;
				pstSelf->ucRxLinkResetFlag = 0;
				pstSelf->ucRxInitFinishFlag = 0;
				pstSelf->uiReInit_Tcn ++;

				if(pstSelf->uiReInit_Tcn >= REINITTIME)
				{
					pstSelf->uiReInit_Tcn = 0;
					pstSelf->ucInitStep = 0;
				}

				break;
		}
	}
	else if(pstSelf->eCS10x_Type == CS101_TYPE_S)
	{
		//作为从站的握手流程
		if(pstSelf->ucRxLinkRequestFlag)  //收到主站的请求链路状态帧
		{
			//重新启动链路
			ClearAllTaskflgs(pstSelf);
			pstSelf->ucRxLinkRequestFlag = 0;
			pstSelf->ucRxLinkResetFlag = 0;
			pstSelf->ucInitStatus = 0;
			SetSendTask(pstSelf, TSKID_MResponse, TSK_PARM_USACT, 0); //发送请求链路状态响应帧
			pstSelf->uiInit_Tcn = WAITTIME_101;
			pstSelf->ucInitStep = 1; //到等待主站的复位链路帧中去
		}

		switch(pstSelf->ucInitStep)
		{
			case 0: //等待主站发送请求链路状态帧  一直等待，无超时计数
				pstSelf->uiInit_Tcn = 0;
				pstSelf->uiInit_Resend_Ncn = 0;
				break;

			case 1: //等待主站发送复位链路帧
				if(pstSelf->uiInit_Tcn)
				{
					if(pstSelf->ucRxLinkResetFlag)  //收到主站的复位链路帧
					{
						pstSelf->ucRxLinkResetFlag = 0;
						SetSendTask(pstSelf, TSKID_Ack, TSK_PARM_USACT, 0); //发送确认帧
						pstSelf->uiInit_Resend_Ncn = 0;
						pstSelf->uiInit_Tcn = 0;

						if(pstSelf->bSimpleInit)  //简单初始化直接发送初始化完成帧
						{
							pstSelf->ucInitStep = 6;
							SetSendTask(pstSelf, TSKID_InitFinish, COT_INIT, 0); // ASDU中未实现初始化完成功能，参数3暂时不用
							pstSelf->ucRxAckFlag = 0;
						}
						else
						{
							pstSelf->uiInit_Tcn = TIMEOUT;
							pstSelf->ucInitStep++;
						}
					}
				}
				else
				{
					pstSelf->ucInitStep = 0xff;
				}

				break;

			case 2: //从站向主站发送请求链路状态帧
				if(pstSelf->uiInit_Resend_Ncn >= RESENDCNT_MAX)
				{
					pstSelf->ucInitStep = 0xff; //握手异常
				}
				else
				{
					SetSendTask(pstSelf, TSKID_RequestLink, TSK_PARM_USACT, 0);
					pstSelf->ucRxLinkStatusFlag = 0;
					pstSelf->uiInit_Tcn = TIMEOUT;
					pstSelf->uiInit_Resend_Ncn++;
					pstSelf->ucInitStep++;
				}

				break;

			case 3: //等待主站的链路状态回复帧
				if(pstSelf->uiInit_Tcn)
				{
					if(pstSelf->ucRxLinkStatusFlag)  //收到主站的请求链路响应帧
					{
						pstSelf->ucRxLinkStatusFlag = 0;
						pstSelf->uiInit_Tcn = 0;
						pstSelf->uiInit_Resend_Ncn = 0;
						pstSelf->ucInitStep++;
					}
				}
				else
				{
					pstSelf->ucInitStep--;
				}

				break;

			case 4: //从站向主站发送复位链路帧
				if(pstSelf->uiInit_Resend_Ncn >= RESENDCNT_MAX)
				{
					pstSelf->ucInitStep = 0xff; //握手异常
				}
				else
				{
					SetSendTask(pstSelf, TSKID_ResetLink, TSK_PARM_USACT, 0); //发送复位链路帧
					pstSelf->ucRxAckFlag = 0;
					pstSelf->uiInit_Tcn = TIMEOUT;
					pstSelf->uiInit_Resend_Ncn++;
					pstSelf->ucInitStep++;
				}

				break;

			case 5: //等待确认帧
				if(pstSelf->uiInit_Tcn)
				{
					if(pstSelf->ucRxAckFlag)  //收到确认帧
					{
						pstSelf->ucRxAckFlag = 0;
						pstSelf->bContinueSendFlag = true;
						SetSendTask(pstSelf, TSKID_InitFinish, COT_INIT, 0); // ASDU中未实现初始化完成功能，参数3暂时不用
						pstSelf->uiInit_Tcn = 0;
						pstSelf->uiInit_Resend_Ncn = 0;
						pstSelf->ucInitStep++;
					}
				}
				else
				{
					pstSelf->ucInitStep--;
				}

				break;

			case 6:
				if(pstSelf->ucRxAckFlag)  //收到确认帧
				{
					pstSelf->ucInitStatus = 1; //初始化结束
					pstSelf->uiInit_Tcn = 0;
					pstSelf->uiInit_Resend_Ncn = 0;
					pstSelf->ucRxLinkStatusFlag = 0;
					pstSelf->ucRxLinkRequestFlag = 0;
					pstSelf->ucRxAckFlag = 0;
					pstSelf->ucRxLinkResetFlag = 0;
					// pstSelf->ucRxInitFinishFlag = 0;
				}

				break;

			case 0xff:
			default:
				pstSelf->uiInit_Tcn = 0;
				pstSelf->uiInit_Resend_Ncn = 0;
				pstSelf->ucRxLinkStatusFlag = 0;
				pstSelf->ucRxLinkRequestFlag = 0;
				pstSelf->ucRxAckFlag = 0;
				pstSelf->ucRxLinkResetFlag = 0;
				// pstSelf->ucRxInitFinishFlag = 0;
				break;
		}
	}

	return;
}

/**
* @brief    101规约ASDU域确认前处理函数 仅针对长帧
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
unsigned short GB101_EncodeFrameHead(CS10xHandle_t pstSelf, VIec101Frame * pstFrame)
{
	unsigned short usLen = 0;
	pstFrame->stFrame68.ucStart1 = START_CODE_101_LONG;
	pstFrame->stFrame68.ucStart2 = START_CODE_101_LONG;
	pstFrame->stFrame68.ucControl = GB101_Control(pstSelf, PRM_MASTER, FCVON, DATA_SEND); //长帧发送都是作为启动站

	if(pstSelf->stAppParameters.iSzOfLinkAddr == 1)                               //链路地址一个字节
	{
		pstFrame->stFrame68.ucaData[0] = pstSelf->stAppParameters.iLinkAddr & 0xff;
		usLen = HEAD_LEN_101 - 1;
	}
	else // 2
	{
		pstFrame->stFrame68.ucaData[0] = pstSelf->stAppParameters.iLinkAddr & 0xff;
		pstFrame->stFrame68.ucaData[1] = (pstSelf->stAppParameters.iLinkAddr >> 8) & 0xff;
		usLen = HEAD_LEN_101;
	}

	return usLen;
}

/**
* @brief    101规约ASDU域确认后处理函数 仅针对101长帧
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void GB101_EncodeFrameTail(CS10xHandle_t pstSelf, VIec101Frame *pstFrame)
{
	unsigned char ucCheckSum = 0; //校验和
	pstFrame->stFrame68.ucLength1 = pstSelf->stSendBuf.usWritePtr - 4;
	pstFrame->stFrame68.ucLength2 = pstSelf->stSendBuf.usWritePtr - 4;
	ucCheckSum = checksum_8(&pstFrame->stFrame68.ucControl, pstSelf->stSendBuf.usWritePtr - 4);
	pstFrame->stFrame68.ucaData[pstSelf->stSendBuf.usWritePtr - 5] = ucCheckSum;
	pstFrame->stFrame68.ucaData[pstSelf->stSendBuf.usWritePtr - 4] = TAIL_CODE_101;
	pstSelf->stSendBuf.usWritePtr += 2;
	return;
}

/**
* @brief    101确认帧组帧
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void GB101_SendAck(CS10xHandle_t pstSelf)
{
	GB101_SendShortX(pstSelf, PRM_SLAVE, ACK_LINK);
	return;
}

/**
* @brief    101响应请求链路状态帧回复
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void GB101_SendLinkStatus(CS10xHandle_t pstSelf)
{
	GB101_SendShortX(pstSelf, PRM_SLAVE, LINKSTATUS);
	return;
}

/**
* @brief    101发送复位链路
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void GB101_SendResetLink(CS10xHandle_t pstSelf)
{
	GB101_SendShortX(pstSelf, PRM_MASTER, RESET_LINK);
	return;
}

/**
* @brief    101发送请求链路
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void GB101_SendRequestLink(CS10xHandle_t pstSelf)
{
	GB101_SendShortX(pstSelf, PRM_MASTER, REQUEST_LINK);
	return;
}

/**
* @brief    101发送测试链路
* @param[in]  pstSelf-规约实体指针
* @param[out] 无
* @return     无
*/
void GB101_SendTestLink(CS10xHandle_t pstSelf)
{
	GB101_SendShortX(pstSelf, PRM_MASTER, TEST_LINK);
	return;
}

/**
* @brief    101短帧复用接口
* @param[in]  pstSelf-规约实体指针
* @param[in]  ucPRM-启动站 从动站
* @param[in]  ucFC-功能码
* @return     无
*/
static void GB101_SendShortX(CS10xHandle_t pstSelf, unsigned char ucPRM, unsigned char ucFC)
{
	VIec101Frame *pstSendFrame = NULL;
	pstSelf->stSendBuf.usWritePtr = 0;
	memset(pstSelf->stSendBuf.pBuf, 0, pstSelf->stSendBuf.usBufSize);
	pstSendFrame = (VIec101Frame *)pstSelf->stSendBuf.pBuf;
	pstSendFrame->stFrame10.ucStart = START_CODE_101_SHORT;
	pstSendFrame->stFrame10.ucControl = GB101_Control(pstSelf, ucPRM, FCVOFF, ucFC);

	if(pstSelf->stAppParameters.iSzOfLinkAddr == 1)  //链路地址一个字节
	{
		pstSendFrame->stFrame10_S.ucAddr = pstSelf->stAppParameters.iLinkAddr & 0xff;
		pstSendFrame->stFrame10_S.ucCS = checksum_8(&pstSendFrame->stFrame10.ucControl, 2);
		pstSendFrame->stFrame10_S.ucTail = TAIL_CODE_101;
		pstSelf->stSendBuf.usWritePtr = SHORT_LEN_S;
	}
	else // 2
	{
		pstSendFrame->stFrame10.ucAddr_L = pstSelf->stAppParameters.iLinkAddr & 0xff;
		pstSendFrame->stFrame10.ucAddr_H = (pstSelf->stAppParameters.iLinkAddr >> 8) & 0xff;
		pstSendFrame->stFrame10.ucCS = checksum_8(&pstSendFrame->stFrame10.ucControl, 3);
		pstSendFrame->stFrame10.ucTail = TAIL_CODE_101;
		pstSelf->stSendBuf.usWritePtr = SHORT_LEN;
	}

	return;
}

/**
* @brief    101规约控制域赋值函数
* @param[in]  pstSelf-规约实体指针
* @param[in]  ucPRM-启动站 从动站
* @param[in]  ucFCV-表征FCB是否有效
* @param[in]  ucFC-功能码
* @param[out] 无
* @return     无
*/
unsigned char GB101_Control(CS10xHandle_t pstSelf, unsigned char ucPRM, unsigned char ucFCV, unsigned char ucFC)
{
	CONTROL101 unControl_101;
	memset(&unControl_101, 0, sizeof(CONTROL101));

	if(pstSelf->eCS10x_Type == CS101_TYPE_M)  //作为主站时
	{
		unControl_101.bits_down.DIR = pstSelf->bDir;
		unControl_101.bits_down.PRM = ucPRM;
		unControl_101.bits_down.FCV = ucFCV;
		unControl_101.bits_down.FC  = ucFC;

		if(ucFCV)  // FCB有效   FCV为0的时候，不翻转也不清0
		{
			// FCB位翻转
			if(pstSelf->ucSelf_FCB)
			{
				unControl_101.bits_down.FCB = 0;
				pstSelf->ucSelf_FCB = 0; //
			}
			else
			{
				unControl_101.bits_down.FCB = 1;
				pstSelf->ucSelf_FCB = 1;
			}
		}

		/*else //FCB无效
		{
		unControl_101.bits_down.FCB = 0;
		//pstSelf->ucSelf_FCB = 0; //无效时清除标志位
		}*/
	}
	else //作为从站时
	{
		unControl_101.bits_up.DIR = pstSelf->bDir;
		unControl_101.bits_up.PRM = ucPRM;
		//unControl_101.bits_up.RES = 0;
		unControl_101.bits_up.DFC = ucFCV; // DFC暂时未处理
		unControl_101.bits_up.FC  = ucFC;

		if(ucFCV)  // FCB有效   FCV为0的时候，不翻转也不清0
		{
			// FCB位翻转
			if(pstSelf->ucSelf_FCB)
			{
				unControl_101.bits_up.RES = 0;
				pstSelf->ucSelf_FCB = 0; //
			}
			else
			{
				unControl_101.bits_up.RES = 1;
				pstSelf->ucSelf_FCB = 1;
			}
		}
	}

	return unControl_101.control;
}

