/********************************************************************
版权所有：	
文件版本： V1.00
文件名称： IEC101.h
生成日期： 2010年04月26日
作    者：hhw
使用范围：

功    能： IEC101规约处理
更新信息：
更新日志1：
修改者:
修改日期:
修改内容:
修改原因:
*********************************************************************/
#ifndef _IEC101_H_
#define _IEC101_H_

#define MAX_101_FRAME_LENTH   	200
#define IEC101_RECVBUF_MAX  	250  	// 101规约，接收的报文，最多40个字节
#define IEC101_FIFO_SIZE		1024

#define IEC101_DATA_TYPE_ASCII  1 		// ASCII8 位码
#define IEC101_DATA_TYPE_UI     3 		// 无符号整数
#define IEC101_DATA_TYPE_CTRL   24 		// 控制字类型(扩展)
#define IEC101_DATA_TYPE_TZ		24		// 16进制显示数据
#define IEC101_DATA_TYPE_I      4 		//整数

#define IEC101_DATA_TYPE_F      7 		// R32.23 =IEEE 标准754 短实数
#define IEC101_DATA_TYPE_DPI    9 		// 双点信息

#define IEC101_DATA_TYPE_SPI     	10 	// 单
#define IEC101_DATA_TYPE_TDPI    	18	// 带时标的报文=CP48 双点信息(DPI) 备用(RES) 四个八位位组时间(TIME) 附加信

#define IEC101_DATA_TYPE_EVENT    	100	// 带时标及参数的报文=CP48 双点信息(DPI) 备用(RES) 四个八位位组时间(TIME) 附加信


#define IEC101_DATA_TYPE_GEN      	22 	// 通用分类回答码(见7.2.6.36)
#define IEC101_DATA_TYPE_STRUCT   	23 	// 数据结构=CPii (GDD GID) =CPii (通用分类数据描述通用分类标

#define IEC101_KOD_NONE  			0	// =实际值(ACTUAL VALUE)
#define IEC101_KOD_ACTVALUE  		1	// =实际值(ACTUAL VALUE)
#define IEC101_KOD_DEFAULT   		2	// =缺省值(DEFAULT VALUE)
#define IEC101_KOD_RANGE     		3	// =量程(最小值最大值步长)(RANGE-minimum value maximum value step
#define IEC101_KOD_DIMENSION  		9	// =量纲(DIMENSION)
#define IEC101_KOD_DESCRIP  		10	// =描述(DESCRIPTION)

#define IEC101_INF_RESET_FCB		2 	// 复位FCB
#define IEC101_INF_RESET_CU			3 	// 单元复位
#define IEC101_INF_RESET_POWER 		4 	// 启动/重新启动


#define IEC101_YX_OFFSET			0x001  //遥信起始地址
#define IEC101_SWITCH_YX_OFFSET		0x0101  //压板状态起始地址
#define IEC101_YC_OFFSET			0x4001  //遥测起始地址
#define IEC101_PULSE_OFFSET			0x6401  //电度起始地址
#define IEC101_YK_OFFSET			0x6001  //遥控起始地址
#define IEC101_EVENT_OFFSET			IEC101_YX_OFFSET  //事件起始地址
#define IEC101_SWITCH_YK_OFFSET		0x6101   //压板遥控起始地址
#define IEC101_RST_DI  				0x6010       

#define IEC101_DPI_YX_OFFSET		0x0100  //双点遥信起始地址


#define IEC101_SETACD(x)		((x)|=0x20)			// 置位ACD位
#define IEC101_SETDIR(x)		((x)|=0x80)			// 置位DIR位
#define IEC101_SETFCB(x)		((x)|=0x20)			// 置位FCB位
#define IEC101_CLRFCB(x)		((x)&=(~0x20))		// 取反FCB位
#define IEC101_SETFCV(x)		((x)|=0x10)			// 置位FCV位
#define IEC101_SETPRM(x)		((x)|=0x40)			// 置位PRM位



#define IEC101_REMOTE_RESET    	(0x00)				// 复位帧

#define IEC101_ECHO_SURE		(0x00)				// 肯定应答
#define IEC101_ECHO_DENY		(0x01)				// 否定应答
#define IEC101_ECHO_DATA       	(0x08)				// 响应数据帧
#define IEC101_ECHO_NO_DATA		(0x09)				// 无所请求的数据帧
#define IEC101_ECHO_LINK_BUSY   (0x01)				// 忙帧
#define IEC101_ECHO_LINK_OK		(0x0B)				// 链路完好
#define IEC101_ECHO_APP_UNOK	(15)					// 链路忙


#define IEC101_CALL_RSTLINK		(0x00)				// 复位链路
#define IEC101_CALL_RSTAPP		(0x01)				// 复位用户进程
#define IEC101_CALL_TESTLINK	(0x02)				// 测试链路
#define IEC101_CALL_DATA     	(0x03)				//数据
#define IEC101_CALL_LINK	   	(0x09)				// 请求链路

#define IEC101_CALL_1	   	(0x0A)				// 请求一级数据
#define IEC101_CALL_2	   	(0x0B)				// 请求二级数据
enum
{
	IEC101_ST_NONE=0,
	IEC101_ST_LINK,
	IEC101_ST_RSTLINK,
	IEC101_ST_DATA,
	IEC101_ST_NUMBER
};
typedef struct IEC101_MASTER  // 101主站 应用层用到的数据
{
	bool bCallAll;
	bool bCallDD;
	bool bSetTime;
	bool bCallOne;    // 召唤一级数据
	bool bTest;
	bool bAppEcho;
	DWORD us0_test;	//最后发送时间点
	DWORD us0_callall;
	DWORD us0_app;
}IEC101_MASTER;


typedef struct IEC101  // 101规约处理结构体
{
	// 通道属性
	BYTE  chnl;
	BYTE  type;
	bool  bMaintainComm;
	u32   LinkCount;	// 连接计数

	// 规约状态
	int   st101;
	bool  bInitCot;
	bool  bSendChange;
	DWORD DTSendChange;
	bool  bfirst_call;
	bool  bFirstFCV;			//  FCV位首次有效
	bool  bResetProcess;		// 复位进程标志
	bool  bMaster;  // 主站规约
	bool  bMasterpH;     //主站平衡101
	bool  bSoeResume;	//总召前续传SOE
	//bool  bSoeRelink;
	bool  bTimeSyn;
	
	BYTE  FCBSave;	
	DWORD dValidTime;	
	DWORD us0_ResetProcess;		// 复位进程计时
	DWORD us0_sendpiece;
	DWORD dTResend;  // 重发间隔
	
	// 计时
	uint32_t us0_sec;	// 秒定时器计时使用
	uint32_t secs;		// 连接建立持续时间
	
	// 帧接收处理
	BYTE  nTypeCounter;         //接受帧类型	
	WORD  nRecvLenth;			//接收到数据计数器
	WORD  nRecvCnt;             //有效数据记
	WORD  nRecvCounter;
	volatile bool  bData;
	BYTE  sum;
	BYTE  recvsum;
	BYTE  recvbuf[IEC_RECV_BUF_SIZE];  // 101规约，接收的报文
	BYTE  extsendbuf[IEC_RECV_BUF_SIZE];
 	BYTE  recv_fifo_buf[IEC101_FIFO_SIZE]; 
 	struct rt_fifo	recv_fifo;

	// 帧发送处理
	// 链路层
	bool btx_buf_m;				// 启动站发送标志(master)
	bool btx_buf_s;				// 从动站发送标志(slave)
	BYTE tx_buf_m[256];			// 启动站发送buf
	BYTE tx_buf_s[256];			// 从动站发送buf
	// 应用层
	int  		tb_index;	// 发送BUF的索引
	iec_tbuf_t	tx_buf[3];  // 带优先级发送BUF，数字越小，优先级越高。
	iec_rbuf_t 	rx_buf;	   // 接收BUF，用于接收主站的一帧报文，目前只在加密报文用，以后应统一

	// 遥测发送处理
	bool  bycsend;
	WORD  ycno;
	long  yc_save[MAX_YC_NUMBER]; 
	uint32_t us0_yc;	// 最后遥测帧发送时间点

	// 对时处理
	uint32_t us0_frame;	// 每个不定长帧报文接收的时刻
	u16			  ms_delay;		// 主站下发的传输延时
	
	// 下面是平衡式规约的变量定义
	bool  bMSend;			//发送标志,表示启动报文已发送，但还没有收到肯定确认。
	bool  bMSend_encrypt;	//安全防护报文发送标志,表示启动报文已发送，但还没有收到肯定确认。
	bool  bMFCB;
	bool  bMFCV;
	bool  bDIR;		// 主站主动发送报文中的DIR位。感觉没有用，因为平衡101中只要是主站发送的报文，DIR应该都为1。
	bool  bTestFrameL;//测试长帧

	//平衡101重发
	BYTE  msend_retries;//重发次数
	DWORD us0_msend;	//最后发送时间点

	//SM2密码报文	
	BYTE  SM2L2;
	volatile bool  bSM2Data;
	DWORD dTRecvPiece;		//接收间隔
	bool  bRmtSM2;
	DWORD us0_SM2Over;
	
	//加密芯片返回信息
	BYTE   secRet; // 加密芯片返回结果，主要处理验签和错误
	struct timespec ct;  //接收到的时间戳
	bool	bEchosecmd5 ;//文件校验MD5，错误信息返回标识
	
	// 级联遥控
	u32  lnk_yk_send_flag;		// 级联遥控
	uint32_t us0_lnk_yk;	// 

	//
	u32  lnk_par_send_flag;		// 级联遥参
	uint32_t us0_lnk_par;	// 
	// GPRS信息获取
	bool bCallGprsInf;	
	bool  bSend;

	
	TRANSFILE   tfile; // 101标准文件传输
	T_FILE         tf;    // 国网规范文件传输
	RMT_SET_DATA	 tr;
	IEC101_MASTER tm;
	FAULT_PARA_BUF tfault;		
#ifdef YPARA_LINK
	msg_data_struct msg_ypara_recv;

	msg_data_struct msg_ypara_send; /*临时组织区,防止堆栈过大*/
	uint32_t us0_msg_ypara;	// 
#endif
#ifdef RCD_STRAN_S
	newrcd_queque	rcd_qt;		/*新产生录波文件名队列*/
#endif
#ifdef FUNC_ENCRY_IN_ONE_SERIAL
	WORD enc_tunnel;		//纬德规约隧道
#endif
}IEC101_DEF;

typedef struct GPRS_INF
{
	bool bInf;
	BYTE data[64];
}GPRS_INF_DEF;

extern GPRS_INF_DEF tGprsInf;

extern IEC101_DEF g_t101;

extern BYTE g_RmtSelcetSection;

void  IEC101_Recv_App(IEC101_DEF *pt) ;
void  IEC101_Recv_Int(IEC101_DEF *pt,u8 byRevData) ;

void IEC101_Init(IEC101_DEF *pt,BYTE chnl);
void IEC101_Applay(IEC101_DEF *pt);
void IEC101_AutoTimer(IEC101_DEF *pt);
void IEC101_FreezeDD(IEC101_DEF *pt ,BYTE type);
void IEC101_Auto_1S(IEC101_DEF *pt);
void IEC101_Send(IEC101_DEF *pt);
int IEC101_PH_GprsInfo(void);


/***********************下面是101规约远方修改定值2016-8-16************************/

void IEC101_SetRead(IEC101_DEF *pt,BYTE *dat);
void IEC101_SetWrite(IEC101_DEF *pt,BYTE *dat);
void IEC101_SectionRead(IEC101_DEF *pt101);			//确认帧
void IEC101_SectionWrite(IEC101_DEF *pt101,u8 *ps);			//确认帧
void IEC101_Asdu_Add(IEC101_DEF *pt,u8 *pdat,u8 len,u8 vsq, u8 cot,u8 type,u16 attr);

/***********************下面是101规约文件传输部分代码2016-8-16************************/

void  IEC101_SegmentContinue(IEC101_DEF *pt);

void IEC101_File_Echo(IEC101_DEF *pt,BYTE *dat); //dat 从报文的帧类型开始

void IEC101_File_Sure(IEC101_DEF *pt,BYTE *dat) ;//dat 从报文的帧类型开始
void IEC101_FreeFile(IEC101_DEF *pt);	
void IEC101_Direct_Echo(IEC101_DEF *pt101,DWORD InfoAddr) ;
u32 IEC101_InfoAddr(void);

u8 get_par_link_101_to_104(BYTE *out,BYTE *in,BYTE parNum,u8 ti);
u8 get_par_link_104_to_104(BYTE *out,BYTE *in,BYTE parNum,u8 ti);

#endif
