/******************************************************************************
版权所有：	
文件名称：	record.c
文件版本：	01.01
创建作者:	sunxi
创建日期：	2013-06-20
功能说明：	录波处理。
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include "head.h"
#ifdef LINUX_KERNEL_APP
#include <linux/delay.h>
#include <linux/kmod.h>
#else
#include <linux/if.h> 
#include <linux/tcp.h>
#include <termios.h>
#include <pthread.h>
#include <sys/prctl.h>
#endif
#include "history_file.h"

/*------------------------------- 宏定义 --------------------------------------
*/
#define DFTU_LINUX_ZX
#define RCD_BACKUP_PATH			"/app/data/data/"
#define RCD_BACKUP_MAX_FILES	120     //最大文件数


#define   	RCD_DI_CHANNEL_CNT	128
#define 	RCD_FILE_PATH		HF_WAVE_DIR
#define 	RCD_MAX_FILES		64     //最大文件数
#define		RCD_WAVE_MAX_NO		9999  //录波最大序号		
#define 	RCD_FILE_NAME		"/tmp/rec_wave.dat"
#define 	RCD_FILE_HEAD_SIZE	256

#define 	RCD_LINE_NUM		8
#define 	RCD_LINE_SIZE		512  //按64个通道计算，每个通道8字节(实际7字节，剩64字节算序号和时间戳)，
#define		RCD_LINE_BUF_SIZE	(RCD_LINE_SIZE*RCD_LINE_NUM)

#define 	RCD_CFG_FILE_SIZE	(128*1024)  //cfg文件的大小

#define 	TIME_WAVE_PRE		(20*NSEC_PER_MS*6)	// 6周波时间，以ns为单位。

#define 	RCD_XDL_NO			(SWITCH_NUM_MAX+1)   //小电流录波文件下标

#define	RCD_MAX_CNT				64    //录波FIFO最大个数,必须是2的n次方 

#define	RCD_ST_IDLE				0
#define	RCD_ST_START_0			1
#define	RCD_ST_START_1			2
#define	RCD_ST_RECORD			3
#define	RCD_ST_RECORD_OK		4
#define	RCD_ST_RECORD_ERR		5
#define	RCD_ST_FILE_OK			6
#define	RCD_ST_FILE_ERR			7


/*------------------------------ 类型结构 -------------------------------------
*/ 
struct rcd_ac
{
	s8 name[EQU_CFG_NAME_LEN];

	u8 	slot;			//板卡槽位地址
	u8 	index;			//AI硬件地址索引
	u8 	owner;			//归属：公共(0)、开关1~开关12(1~12)
	u8 	type;			//AI类型
	
	u8 channel;			// 内部通道序号，用来索引采样点数据
	u8 is_ct_inverse;	// CT是否反向
	u8 is_not_owner;	// 如果为1，owner值无效。
	u8 reserved[5];
	
	float	factor_e_k;	// 有效值理论比例系数
	float	factor_e_c;	// 有效值校准比例系数
	float	factor_p_k;	// 相位理论修正系数
	float	factor_p_c;	// 相位校准修正系数
};

struct rcd_di
{
	s8 name[EQU_CFG_NAME_LEN];
};

struct rcd_do
{
	s8 name[EQU_CFG_NAME_LEN];
};

struct rcd_file_head
{
	struct cfg_file_head cfh;		

	// 
	s8	equ_name[16];
	s8	version[16];
	struct timespec ts_begin;
	u32 type;
	u32 dots_per_period;

	// 通道配置头
	// AC
	u32	ac_addr;	//地址
	u32	ac_num;		//个数

	// DI
	u32	di_addr;	//地址
	u32	di_num;		//个数

	// DO
	u32	do_addr;	//地址
	u32	do_num;		//个数

	// 采样点
	u32	dot_addr;	//地址
	u32	dot_num;	//个数
};


// 	站名、录波装置编号、版本年代
struct cfg_file_srr
{
	char station_name[65];  // 站名包括最后一个字符'\0',下同
	char rec_dev_id[65];  //录波装置编号
	char rev_year[5];     //版本年代
};


// 	通道的种类和数量
struct cfg_file_TT
{
	int  A;//模拟通道的数目
	int  D;//开关量通道的数目

};


// 	模拟通道信息
struct cfg_file_TT_A
{

	int An;  //通道的索引
	char ch_id[65];//通道标识符
	char Ph[3];//通道相位标识符
	char Ccb[65];//被检测的电路组件
	char Uu[33];//通道的单位
	float a;//通道点值的倍数
	float b;//通道值偏移量
	float skew;//通道从采样开始的时间偏移（us）
	int min;//此通道中的最小值
	int max;//此通道中的最大值
	float primary;//通道电压或电流变压器一次线圈比例系数
	float secondary;//通道电压或电流变压器二次线圈比例系数
	char ps[2];//采用primary 值还是secondary值;决定转换后的ax＋b通道值是一次侧值还是二次侧值	
};


// 	开关量（数字）通道信息
struct cfg_file_TT_D
{

	int Dn; //status通道索引
	char ch_id[65];//通道名称
	char ph[3];//通道的相位标识符
	char ccbm[65];//被检测的电路组件
	int Y;//开关量通道的状态
};

// 	采样速率信息
struct cfg_file_samp_info
{
	int nrates; //DAT文件中所用到的采样速率个数
	float samp;//采样频率
	int endsamp;//最终的采样数
};

// 	时间/日期信息
struct cfg_file_date_info
{
	char firsttime[27];
	char trigger_point_ime[27];
};

//录波配置（.CFG）文件定义
struct cfg_file_struct
{
	struct cfg_file_srr srr;  
	struct cfg_file_TT  tt;
	struct cfg_file_TT_A *tt_a;
	struct cfg_file_TT_D *tt_d;
	float Lf; //线路频率
	struct cfg_file_samp_info si;
	struct cfg_file_date_info date_i;
	char ft[7]; //DAT文件格式
	char timemult[2];//时间倍乘因数 


	int  tt_a_cnt;   //模拟通道数
	int  *tt_a_index; //对应的配置索引

	int  tt_d_cnt;    //数字量通道数
	int  *tt_d_index;	 //对应的配置索引
	u8  chnl[64]; //通道号
	
};


// DAT文件格式
struct dat_file_struct
{
	unsigned int n;//采样编号
	unsigned int timestamp;//采样时间
	int An[CFG_ADC_CHANNEL];//模拟通道数据
	int Dn[RCD_DI_CHANNEL_CNT];//开关量通道
} ;

struct rcd 
{
	// 录波类型 
	u32 type;     	
	u32 sw;//开关序号

	// 以采样点索引为时间单位的变量
	u32	dt_begin;	// 开始时间点
	u32	dt_cur;		// 当前时间点
	u32	dt_end;		// 结束时间点

	// 录波开始时刻
	struct timespec ts_begin;

	// 录波文件相关变量
	int				f_index;
	loff_t			f_offset;
	struct file * 	f_handle;	
	int  fd_cfg;
	int  fd_dat;
	
	int new_waveno; //故障录波新序号  
	int state;  	//录波状态
	int reuslt;  	//录波结果  0表示成功

	char rcd_working; //同一线路的录波类型
	//int 	rcd_type_buf[RCD_BUF_TYPE_NUM]; //缓存录波类型
	//int 	b_head;
	//int	b_tail;
	
	struct cfg_file_struct  f_cfs;
	struct dat_file_struct  f_dfs;
	int  sw_chancnt;  //开关通道数
	int  pub_cnt;    //公共通道数
	char tmp_cfg[128];	//临时文件名
	char tmp_dat[128];	//临时文件名
	char *pdat_mem;		//存放dat文件内容的内存指针
	u32 pdat_mem_pos;  //内容的实际长度
	u32 pdat_mem_size; //分配的内存大小
	char *pcfg_mem;		//存放cfg文件内容的内存指针
	u32 pcfg_mem_pos;  //内容的实际长度
	u32 pcfg_mem_size;	//分配的内存大小
	int  *pAn; //模拟通道数据
	int  pAn_size; //数据维度
	int  pAn_no; //序号 
	u8  *pDn; //开关量通道数据
	int  pDn_size; //数据维度
	int  pDn_no; //序号 	
	unsigned int samp_t; //采样间隔
} ;



/*------------------------------ 全局变量 -------------------------------------
*/

int g_rcd_init;
u32 g_rcd_working;
struct rcd g_rcd[RCD_MAX_CNT];
struct rcd g_rcd_xdl[1];
int g_new_waveno[SWITCH_NUM_MAX+2];
static volatile u8 rcd_head=0;
static volatile u8 rcd_tail=0;
static int rcd_sd_flag=0;

#ifdef LINUX_KERNEL_APP
static struct task_struct * g_ts_rcd;
static struct task_struct * g_ts_rcd_writefile; //写文件任务
static DECLARE_WAIT_QUEUE_HEAD(g_wq_rcd);
static int g_wq_rcd_flag;

#else
static pthread_t _rcd_thread_tid = 0;
static pthread_t _rcd_writefile_tid = 0;
static int g_rcd_exit_flag = 0;
static int g_rcd_writefile_exit_flag = 0;
pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t g_mutex;
pthread_condattr_t attr;

#endif

extern float g_freq; 
//static char g_file_buf[4096];
char wave_name[RECORD_FILES_MAX][40];	

int g_wave_filetype = 1; //录波文件格式.默认是BINARY
bool g_rcd_type_enable[RECORD_TYPE_NUM];


/*------------------------------ 函数声明 -------------------------------------
*/
static void _rcd_save_to_flash(struct rcd *prcd);
int _rcd_close_wave(struct rcd *prcd);
int _rcd_soft_isr(int irq, void *dev_id);
int _rcd_thread(void * unused);
int _rcd_writefile_thread(void * unused);
//获取对应的故障录波序号
void _rcd_get_waveno(void);

int rcd_write_cfg(struct rcd *prcd);
int rcd_write_dat(struct rcd *prcd);

void  _rcd_uninit_wave(struct rcd *prcd);


/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/

//获取FIFO数量即已经录波的个数
int rcd_get_fifo_count(int head, int tail, int count)
{

	if(head >=  tail)
	{
		return (head - tail);
	}

	return  ((count - tail)+head);

}

//获取配置的数字量开关通道数
static  int rcd_get_di_chan_cnt(u32 sw)
{
	int i=0;
	int cnt = 0;
	
	for(i=0; i< g_equ_config->di_num; i++)
	{
	
		if( (g_equ_config_di[i].type == 0) || (g_equ_config_di[i].owner != (sw+1)))
		{
			continue;
		}

		cnt++;
	}

	return cnt;
}

#if 0
//获取配置的开关通道数
static  int rcd_get_chan_cnt_all(void) 
{
	int i=0;
	int cnt = 0;
	
	for(i=0; i< g_equ_config->ac_num; i++)
	{
	
		if( g_equ_config_ac[i].type == 0)
		{
			continue;
		}

		cnt++;
	 	 
	}

	return cnt;
}
#endif

int rcd_get_sw_addr(u32 sw)
{
	int index;
	u16 cp=0;
	index = plc_yx2index(sw+1,SW_DI_KRHW+1);
	if(index >= 0)
	{
		cp = g_lp[index].cp;
	}
	 	
	return cp;
}


#if 0
//获取配置的模拟开关通道数
static  int rcd_get_chan_cnt(u32 sw)
{
	int i=0;
	int cnt = 0;
	
	for(i=0; i< g_equ_config->ac_num; i++)
	{
	
		if( g_equ_config_ac[i].type == 0)
		{
			continue;
		}

	 	if( g_equ_config_ac[i].owner == (sw+1))
		{
			cnt++;
	 	}
	}

	return cnt;
}


//获取配置的公共通道数
static  int rcd_get_pub_cnt(void)
{
	int i=0;
	int cnt = 0;
	
	for(i=0; i< g_equ_config->ac_num; i++)
	{
	
		if( g_equ_config_ac[i].type == 0)
		{
			continue;
		}

	 	if( g_equ_config_ac[i].owner == 0)
		{
			cnt++;
	 	}
	}

	return cnt;
}
#endif
//初始化开关模拟通道

int rcd_init_sw_A(struct rcd *prcd)
{
	int i=0;
	int type1 = 0;
	int index;
	char pabc[]={0,0, 0};
	int scale = 0;
	float f;
	u32 sw=prcd->sw;
	//u32 type = prcd->type;
	for(i=0;i<prcd->f_cfs.tt.A;i++)
	{
		index = prcd->f_cfs.tt_a_index[i];
		type1 =  g_equ_config_ac[index].type -1;
		
		//开关
		if(g_equ_config_ac[index].owner==(sw+1))
		{		    
			prcd->f_cfs.tt_a[i].An = i+1;
			sprintf(prcd->f_cfs.tt_a[i].ch_id,"%s%d" ,  g_sw_ac_desc[type1].name, g_equ_config_ac[index].owner);
			if(strstr( prcd->f_cfs.tt_a[i].ch_id, "IA"))
			{
				pabc[0]='A';
				pabc[1]= 0;
			}
			else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "IB"))
			{
				pabc[0]='B';
				pabc[1]= 0;
			}
			else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "IC"))
			{
				pabc[0]='C';
				pabc[1]= 0;
			}
			else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "I0"))
			{
				prcd->f_cfs.tt_a[i].ch_id[1]='Z';
				pabc[0]='Z';
				pabc[1]= 0;
			}
			else
			{
				pabc[0]=0;
			}		

			sprintf(prcd->f_cfs.tt_a[i].Ph, "%s", pabc);
			strcpy(prcd->f_cfs.tt_a[i].Uu, g_unit[g_sw_ac_desc[type1].unit].name);
				
	
		}
		else if(g_equ_config_ac[index].owner==0)
		{
			prcd->f_cfs.tt_a[i].An = i+1;
			strcpy(prcd->f_cfs.tt_a[i].ch_id, g_pub_ac_desc[type1].name);
			
			if(strlen(prcd->f_cfs.tt_a[i].ch_id)>3)
			{
				pabc[0]=prcd->f_cfs.tt_a[i].ch_id[1];
				pabc[1]=prcd->f_cfs.tt_a[i].ch_id[2];
			}
			else
			{
				if(strstr( prcd->f_cfs.tt_a[i].ch_id, "U0"))
				{
					prcd->f_cfs.tt_a[i].ch_id[1]='Z';
					pabc[0]='Z';
					pabc[1]=0;
				}
				else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "US"))
				{
					pabc[0]=0;
				}
				else
				{
					pabc[0]=prcd->f_cfs.tt_a[i].ch_id[1];
					pabc[1]=0;
				}
			}

			sprintf(prcd->f_cfs.tt_a[i].Ph, "%s", pabc);
			
			strcpy(prcd->f_cfs.tt_a[i].Uu, g_unit[g_pub_ac_desc[type1].unit].name);
		}

		scale= equ_get_ac_scale(g_equ_config_ac[index].slot, g_equ_config_ac[index].index);
		factor_e_c_get(g_equ_config_ac[index].slot,g_equ_config_ac[index].index,&f);

		prcd->f_cfs.tt_a[i].a =f/factor_e_k(scale)*1.4142;
		prcd->f_cfs.tt_a[i].b = 0;
		prcd->f_cfs.tt_a[i].skew = 0;
		prcd->f_cfs.tt_a[i].max = 32767;
		prcd->f_cfs.tt_a[i].min= -32767;
		prcd->f_cfs.tt_a[i].primary = sw_get_chnl_ps(index,1);
		prcd->f_cfs.tt_a[i].secondary= sw_get_chnl_ps(index,0);
		prcd->f_cfs.tt_a[i].ps[0]='S';
		prcd->f_cfs.tt_a[i].ps[1]=0;
			
			 
		//rt_printf("%d,%s,%s,%s,", g_rcd[sw].f_cfs.tt_a[i].An, g_rcd[sw].f_cfs.tt_a[i].ch_id, g_rcd[sw].f_cfs.tt_a[i].Ph, g_rcd[sw].f_cfs.tt_a[i].Uu );
		//rt_printf("%f,%f,%f,%d,%d,", g_rcd[sw].f_cfs.tt_a[i].a, g_rcd[sw].f_cfs.tt_a[i].b, g_rcd[sw].f_cfs.tt_a[i].skew, g_rcd[sw].f_cfs.tt_a[i].min, g_rcd[sw].f_cfs.tt_a[i].max);

		//rt_printf("%f,%f,%s\r\n", g_rcd[sw].f_cfs.tt_a[i].primary, g_rcd[sw].f_cfs.tt_a[i].secondary, g_rcd[sw].f_cfs.tt_a[i].ps);
		
	}

	return 0;
		}


//初始化开关模拟通道
int rcd_init_DI(struct rcd *prcd)
{
	int i=0;
	int type1 = 0;
	int index;
	int sw = prcd->sw;
//	u32 type = prcd->type;
	

	
	for(i=0;i<prcd->f_cfs.tt.D;i++)
	{
		index = prcd->f_cfs.tt_d_index[i];
		type1 =  g_equ_config_di[index].type -1;
		
		//开关
		if(g_equ_config_di[index].owner==(sw+1))
		{		    
			prcd->f_cfs.tt_d[i].Dn = i+1;
			sprintf(prcd->f_cfs.tt_d[i].ch_id,"开关%d %s" ,g_equ_config_di[index].owner, g_sw_di_name[type1]);
				
	
		}		
	}
	
	
	return 0;
}

//初始化开关模拟通道
int rcd_init_A_all(struct rcd *prcd)
		{
	int i=0;
	int type1 = 0;
	int index;
	char pabc[]={0,0, 0};
//	u32 sw = prcd->sw;
//	u32 type=prcd->type;
	int scale = 0;
	float f;
		    
	for(i=0;i<prcd->f_cfs.tt.A;i++)
	{
		index = prcd->f_cfs.tt_a_index[i];
		type1 =  g_equ_config_ac[index].type -1;
		
		//开关
		if(g_equ_config_ac[index].owner!=0)
		{		    
			prcd->f_cfs.tt_a[i].An = i+1;
			sprintf(prcd->f_cfs.tt_a[i].ch_id,"%s%d" , g_sw_ac_desc[type1].name, g_equ_config_ac[index].owner);
			if(strstr( prcd->f_cfs.tt_a[i].ch_id, "IA"))
			{
				pabc[0]='A';
				pabc[1]= 0;
			}
			else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "IB"))
			{
				pabc[0]='B';
				pabc[1]= 0;
			}
			else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "IC"))
			{
				pabc[0]='C';
				pabc[1]= 0;
			}
			else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "I0"))
			{
				prcd->f_cfs.tt_a[i].ch_id[1]='Z';			
				pabc[0]='Z';
				pabc[1]= 0;
			}			
			else
			{
				pabc[0]=0;
			}		

			sprintf(prcd->f_cfs.tt_a[i].Ph, "%s", pabc);
			strcpy(prcd->f_cfs.tt_a[i].Uu, g_unit[g_sw_ac_desc[type1].unit].name);
				
	
		}
		else if(g_equ_config_ac[index].owner==0)
		{
			prcd->f_cfs.tt_a[i].An = i+1;
			strcpy(prcd->f_cfs.tt_a[i].ch_id, g_pub_ac_desc[type1].name);

			if(strlen(prcd->f_cfs.tt_a[i].ch_id)>3)
			{
				pabc[0]=prcd->f_cfs.tt_a[i].ch_id[1];
				pabc[1]=prcd->f_cfs.tt_a[i].ch_id[2];
			}
			else
			{
				if(strstr( prcd->f_cfs.tt_a[i].ch_id, "U0"))
				{
					prcd->f_cfs.tt_a[i].ch_id[1]='Z';
					pabc[0]='Z';
					pabc[1]=0;
				}
				else if(strstr( prcd->f_cfs.tt_a[i].ch_id, "US"))
				{
					pabc[0]=0;
				}
				else
				{
					pabc[0]=prcd->f_cfs.tt_a[i].ch_id[1];
					pabc[1]=0;
				}
			}
			


			sprintf(prcd->f_cfs.tt_a[i].Ph, "%s", pabc);
			
			strcpy(prcd->f_cfs.tt_a[i].Uu, g_unit[g_pub_ac_desc[type1].unit].name);			
		}

		scale = equ_get_ac_scale(g_equ_config_ac[index].slot, g_equ_config_ac[index].index);
		factor_e_c_get(g_equ_config_ac[index].slot,g_equ_config_ac[index].index,&f);
	
		prcd->f_cfs.tt_a[i].a =f/factor_e_k(scale)*1.4142;
		prcd->f_cfs.tt_a[i].b = 0;
		prcd->f_cfs.tt_a[i].skew = 0;
		prcd->f_cfs.tt_a[i].max = 32767;
		prcd->f_cfs.tt_a[i].min= -32767;
		prcd->f_cfs.tt_a[i].primary =sw_get_chnl_ps(index,1);
		prcd->f_cfs.tt_a[i].secondary= sw_get_chnl_ps(index,0);
		prcd->f_cfs.tt_a[i].ps[0]='S';
		prcd->f_cfs.tt_a[i].ps[1]=0;
	

		//rt_printf("%d,%s,%s,%s,", g_rcd[sw].f_cfs.tt_a[i].An, g_rcd[sw].f_cfs.tt_a[i].ch_id, g_rcd[sw].f_cfs.tt_a[i].Ph, g_rcd[sw].f_cfs.tt_a[i].Uu );
		//rt_printf("%f,%f,%f,%d,%d,", g_rcd[sw].f_cfs.tt_a[i].a, g_rcd[sw].f_cfs.tt_a[i].b, g_rcd[sw].f_cfs.tt_a[i].skew, g_rcd[sw].f_cfs.tt_a[i].min, g_rcd[sw].f_cfs.tt_a[i].max);

		//rt_printf("%f,%f,%s\r\n", g_rcd[sw].f_cfs.tt_a[i].primary, g_rcd[sw].f_cfs.tt_a[i].secondary, g_rcd[sw].f_cfs.tt_a[i].ps);
		
	}

	return 0;
}
int rcd_get_pub_cnt(u32 sw)
{
	int i=0;
	int cnt = 0;

	#if 1
	// 电压
	for(i=0; i< PUB_AC_NUM; i++)
	{
		if((short)g_sw_pub.ac_cfg_index[i] != INDEX_INVALLID)
		{

			//电压组2
			if(pRunSet->tSwSet[sw].bTT_Power_v2)
			{
				if(i >= PUB_AC_UA2)
				{
					cnt++;
				}
				else
				{
					continue;
				}
			}
			else //电压组1
			{
				if(i < PUB_AC_UA2)
				{
					cnt++;
				}
				else
				{
					continue;
				}

			}

			
		}
	}	
	#else
	 for(i=0;i<g_equ_config->ac_num;i++)
	 {
 		if( g_equ_config_ac[i].type == 0)
		{
			continue;
		}	 
		if( g_equ_config_ac[i].owner == 0)
		{
			if(pRunSet->tSwSet[sw].bTT_Power_v2)
			{
				if(g_equ_config_ac[i].type >= PUB_AC_UA2)
				{
					cnt++;
				}
			}
			else
			{

				if(g_equ_config_ac[i].type < PUB_AC_UA2)
				{
					cnt++;
				}
				

			}
		}
	 }
	#endif
	return cnt;
}
int rcd_init_channel(struct rcd *prcd)
{
	int i;
	int cnt = 0;
	int pub_cnt = 0;
	struct rtc_time_t   rtc;
	struct timespec ts;	
	char tmp_buf[64];
	u32 sw = prcd->sw;
//	u32 type = prcd->type;

	memset(tmp_buf, 0, sizeof(tmp_buf));
	set_get_fixed_arg(FIXED_SET_MAU, tmp_buf, sizeof(tmp_buf));
	sprintf(prcd->f_cfs.srr.station_name, "%s ", tmp_buf);
	memset(tmp_buf, 0, sizeof(tmp_buf));
	set_get_fixed_arg(FIXED_SET_TPE, tmp_buf, sizeof(tmp_buf));
	strcat(prcd->f_cfs.srr.station_name, tmp_buf);
	sprintf(prcd->f_cfs.srr.rec_dev_id, "%03d", 1);
	sprintf(prcd->f_cfs.srr.rev_year, "%d", 1999);

	//rt_printf("sw=%d\r\n", sw);
		
	cnt = g_sw_ac_num[sw];//rcd_get_chan_cnt(sw);
	#ifdef BSP_TYPE_FTU
	pub_cnt = g_pub_ac_num;//rcd_get_pub_cnt();
	#else
	pub_cnt = rcd_get_pub_cnt(sw);//g_pub_ac_num;//rcd_get_pub_cnt();
	#endif
	
 	prcd->sw_chancnt = cnt;
	prcd->f_cfs.tt_a_cnt = cnt + pub_cnt;

	prcd->f_cfs.tt_d_cnt = 0;

	if(cnt == 0)
	{
		return -1;
	}


	
	{
		//模拟通道
		prcd->f_cfs.tt_a = rt_malloc((cnt+pub_cnt)*sizeof(struct cfg_file_TT_A  ));
		if(!prcd->f_cfs.tt_a)
		{
			return -1;
		}
		memset(prcd->f_cfs.tt_a , 0, (cnt+pub_cnt) *sizeof(struct cfg_file_TT_A ));

		//模拟通道对应的配置索引
		prcd->f_cfs.tt_a_index = rt_malloc((cnt+pub_cnt) *sizeof(int));
		if(!prcd->f_cfs.tt_a_index)
		{
			rt_free(prcd->f_cfs.tt_a);
			return -1;
		}

		
	#if 1			 
		cnt  = 0;
		#ifdef BSP_TYPE_FTU
		// 电压
		for(i=0; i< PUB_AC_NUM; i++)
		{
			if((short)g_sw_pub.ac_cfg_index[i] != INDEX_INVALLID)
			{
				prcd->f_cfs.tt_a_index[cnt] = g_sw_pub.ac_cfg_index[i]; 
				prcd->f_cfs.chnl[cnt] =  equ_get_ac_channel(g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].slot, g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].index);
				cnt++;	
				
			}
		}

		// 电流
		for(i=0; i< SW_AC_NUM; i++)
		{
			if((short)g_sw[sw].ac_cfg_index[i] != INDEX_INVALLID)
			{
				prcd->f_cfs.tt_a_index[cnt] = g_sw[sw].ac_cfg_index[i];
				prcd->f_cfs.chnl[cnt] =  equ_get_ac_channel(g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].slot, g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].index);
				cnt++;	
				
			}
		}		
		#else
		
		// 电压
		for(i=0; i< PUB_AC_NUM; i++)
		{
			if((short)g_sw_pub.ac_cfg_index[i] != INDEX_INVALLID)
			{

				//电压组2
				if(pRunSet->tSwSet[sw].bTT_Power_v2)
				{
					if(i >= PUB_AC_UA2)
					{
						prcd->f_cfs.tt_a_index[cnt] = g_sw_pub.ac_cfg_index[i];
						prcd->f_cfs.chnl[cnt] =  equ_get_ac_channel(g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].slot, g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].index);
						cnt++;							
					}
					else
					{
						continue;
					}
				}
				else //电压组1
				{
					if(i < PUB_AC_UA2)
					{
						prcd->f_cfs.tt_a_index[cnt] = g_sw_pub.ac_cfg_index[i];
						prcd->f_cfs.chnl[cnt] =  equ_get_ac_channel(g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].slot, g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].index);
						cnt++;							
					}
					else
					{
						continue;
					}

				}

				
			}
		}

		// 电流
		for(i=0; i< SW_AC_NUM; i++)
		{
			if((short)g_sw[sw].ac_cfg_index[i] != INDEX_INVALLID)
			{
				prcd->f_cfs.tt_a_index[cnt] = g_sw[sw].ac_cfg_index[i]; 
				prcd->f_cfs.chnl[cnt] =  equ_get_ac_channel(g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].slot, g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].index);
				cnt++;					
			}
		}
		
		#endif
		
	#else 
	//记住原来的索引
		cnt  = 0;
		for(i=0; i< g_equ_config->ac_num; i++)
		{
		
			if( g_equ_config_ac[i].type == 0)
			{
				continue;
			}

			if( g_equ_config_ac[i].owner == (sw+1))
			{
				prcd->f_cfs.tt_a_index[cnt++] = i; 
			}
			else if( g_equ_config_ac[i].owner == 0)
			{
				#ifdef BSP_TYPE_FTU
				prcd->f_cfs.tt_a_index[cnt++] = i; 
				#else
				//电压组2
				if(pRunSet->tSwSet[sw].bTT_Power_v2)
				{
					if(g_equ_config_ac[i].type >= PUB_AC_UA2)
					{
						prcd->f_cfs.tt_a_index[cnt++] = i;
					}
					else
					{
						continue;
					}
				}
				else //电压组1
				{
					if(g_equ_config_ac[i].type < PUB_AC_UA2)
					{
						prcd->f_cfs.tt_a_index[cnt++] = i;
					}
					else
					{
						continue;
					}

				}
				#endif
			}
				
		}
		
#endif
	}


	//开关量通道数
	cnt = rcd_get_di_chan_cnt(sw);

	prcd->f_cfs.tt_d_cnt = cnt;	


	//开入(开关量)通道
	prcd->f_cfs.tt_d = rt_malloc(cnt*sizeof(struct cfg_file_TT_D  ));
	if(!prcd->f_cfs.tt_d)
	{

		rt_free(prcd->f_cfs.tt_a);
		rt_free(prcd->f_cfs.tt_a_index);
		return -1;
	}

	memset(prcd->f_cfs.tt_d , 0, cnt *sizeof(struct cfg_file_TT_D ));

	//开关量通道对应的配置索引
	prcd->f_cfs.tt_d_index = rt_malloc(cnt *sizeof(int));
	if(!prcd->f_cfs.tt_d_index)
	{
		rt_free(prcd->f_cfs.tt_a);
		rt_free(prcd->f_cfs.tt_a_index);
		rt_free(prcd->f_cfs.tt_d);
		return -1;
	}


	//记住原来的索引
	cnt  = 0;
	for(i=0; i< g_equ_config->di_num; i++)
	{
	
		if( (g_equ_config_di[i].type == 0) || (g_equ_config_di[i].owner != (sw+1)))
		{
			continue;
		}


		
		prcd->f_cfs.tt_d_index[cnt++] = i; 	 
	
			
	}




	//模拟通道数	
	prcd->f_cfs.tt.A = prcd->f_cfs.tt_a_cnt ;
	//开关量通道数
	prcd->f_cfs.tt.D = prcd->f_cfs.tt_d_cnt;

	//rt_printf("%s,%s,%s\r\n", g_rcd[sw].f_cfs.srr.station_name,  g_rcd[sw].f_cfs.srr.rec_dev_id,  g_rcd[sw].f_cfs.srr.rev_year);
	//rt_printf("TT:%dA,%dD\r\n", g_rcd[sw].f_cfs.tt.A, g_rcd[sw].f_cfs.tt.D);
	rcd_init_sw_A(prcd);
	rcd_init_DI(prcd);
	prcd->f_cfs.Lf = g_freq;
	prcd->f_cfs.si.nrates = 1;
	if((g_freq < 45.0) || (g_freq > 55.0) )
	{
	prcd->f_cfs.si.samp = 6400;
	}
	else
	{
		prcd->f_cfs.si.samp =  g_freq * CFG_ADC_DOTS_PER_PERIOD*ADC_REC_SAMPLE_RATE; 	
	}

	prcd->samp_t = 1000000/prcd->f_cfs.si.samp;
	
	prcd->f_cfs.si.endsamp = (prcd->dt_end - prcd->dt_begin)*ADC_REC_SAMPLE_RATE;

	ts = prcd->ts_begin;
	timespec_to_rtc(ts,  &rtc, 0);
	sprintf(prcd->f_cfs.date_i.firsttime, "%02d/%02d/%04d,%02d:%02d:%02d.%06d", rtc.day, rtc.month,rtc.year+2000,  rtc.hour, rtc.min, rtc.ms/1000,  (rtc.ms%1000)*1000);

	ts.tv_nsec +=TIME_WAVE_PRE;
	if(ts.tv_nsec >= 1000000000)
	{
	    ts.tv_sec  += 1;
	    ts.tv_nsec -= 1000000000;
	}	

	timespec_to_rtc(ts,  &rtc, 0);
	sprintf(prcd->f_cfs.date_i.trigger_point_ime, "%02d/%02d/%04d,%02d:%02d:%02d.%06d", rtc.day, rtc.month,rtc.year+2000,  rtc.hour, rtc.min, rtc.ms/1000,  (rtc.ms%1000)*1000);
	if(g_wave_filetype==0)
	{
		strcpy(prcd->f_cfs.ft,"ASCII");
	}
	else
	{
		strcpy(prcd->f_cfs.ft,"BINARY");
	}
	prcd->f_cfs.timemult[0] = '1'; 
	
	return 0;
}

int rcd_init_channel_all(struct rcd *prcd)
{
	int i,j;
	int cnt = 0;
	int pub_cnt = 0;
	struct rtc_time_t   rtc;
	struct timespec ts;	
//	u32 sw = prcd->sw;
//	u32 type=prcd->type;
	char tmp_buf[64];

	memset(tmp_buf, 0, sizeof(tmp_buf));
	set_get_fixed_arg(FIXED_SET_MAU, tmp_buf, sizeof(tmp_buf));
	sprintf(prcd->f_cfs.srr.station_name, "%s ", tmp_buf);
	memset(tmp_buf, 0, sizeof(tmp_buf));
	set_get_fixed_arg(FIXED_SET_TPE, tmp_buf, sizeof(tmp_buf));
	strcat(prcd->f_cfs.srr.station_name, tmp_buf);
	sprintf(prcd->f_cfs.srr.rec_dev_id, "%03d", 1);
	sprintf(prcd->f_cfs.srr.rev_year, "%d", 1999);
	
	//rt_printf("sw=%d\r\n", sw);
		
	cnt = g_sw_ac_num[SWITCH_NUM_MAX];//rcd_get_chan_cnt_all();

	prcd->f_cfs.tt_a_cnt = cnt;
	prcd->f_cfs.tt_d_cnt = 0;
	
	
	if(cnt == 0)
	{
		return -1;
	}


	
	{
		//模拟通道
		prcd->f_cfs.tt_a = rt_malloc((cnt+pub_cnt)*sizeof(struct cfg_file_TT_A  ));
		if(!prcd->f_cfs.tt_a)
		{
			return -1;
		}
		memset(prcd->f_cfs.tt_a , 0, (cnt+pub_cnt) *sizeof(struct cfg_file_TT_A ));

		//模拟通道对应的配置索引
		prcd->f_cfs.tt_a_index = rt_malloc((cnt+pub_cnt) *sizeof(int));
		if(!prcd->f_cfs.tt_a_index)
		{
			rt_free(prcd->f_cfs.tt_a);
			return -1;
		}

		
		#if 1
		//记住原来的索引
		cnt  = 0;
		// 电压
		for(i=0; i < PUB_AC_NUM; i++)
		{
			if((short)g_sw_pub.ac_cfg_index[i] != INDEX_INVALLID)
			{
				prcd->f_cfs.tt_a_index[cnt] = g_sw_pub.ac_cfg_index[i]; 
				prcd->f_cfs.chnl[cnt] =  equ_get_ac_channel(g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].slot, g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].index);
				cnt++;	
			}
		}
		
		for(i=0; i<SWITCH_NUM_MAX; i++)
		{
			// 电流
			for(j=0; j < SW_AC_NUM; j++)
			{
				if((short)g_sw[i].ac_cfg_index[j] != INDEX_INVALLID)
				{
					prcd->f_cfs.tt_a_index[cnt] = g_sw[i].ac_cfg_index[j]; 
					
					prcd->f_cfs.chnl[cnt] =  equ_get_ac_channel(g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].slot, g_equ_config_ac[prcd->f_cfs.tt_a_index[cnt]].index);
					cnt++;
				}
			}
		}
		#else
		//记住原来的索引
		cnt  = 0;
		for(i=0; i< g_equ_config->ac_num; i++)
		{
		
			if( g_equ_config_ac[i].type == 0)
			{
				continue;
			}


			
			prcd->f_cfs.tt_a_index[cnt++] = i; 	 
		
				
		}

		#endif
	}	

	//模拟通道数	
	prcd->f_cfs.tt.A = prcd->f_cfs.tt_a_cnt ;
	//开关量通道数
	prcd->f_cfs.tt.D = prcd->f_cfs.tt_d_cnt;

	//rt_printf("%s,%s,%s\r\n", g_rcd[sw].f_cfs.srr.station_name,  g_rcd[sw].f_cfs.srr.rec_dev_id,  g_rcd[sw].f_cfs.srr.rev_year);
	//rt_printf("TT:%dA,%dD\r\n", g_rcd[sw].f_cfs.tt.A, g_rcd[sw].f_cfs.tt.D);
	rcd_init_A_all(prcd);
	prcd->f_cfs.Lf = freq_get(0);
	prcd->f_cfs.si.nrates = 1;
	if((g_freq < 45.0) || (g_freq > 55.0) )
	{
	prcd->f_cfs.si.samp = 6400;
	}
	else
	{
		prcd->f_cfs.si.samp =  g_freq * CFG_ADC_DOTS_PER_PERIOD*ADC_REC_SAMPLE_RATE; 	
	}	
	prcd->samp_t = 1000000/prcd->f_cfs.si.samp;
	prcd->f_cfs.si.endsamp = (prcd->dt_end - prcd->dt_begin)*ADC_REC_SAMPLE_RATE;

	ts = prcd->ts_begin;
	timespec_to_rtc(ts,  &rtc, 0);
	sprintf(prcd->f_cfs.date_i.firsttime, "%02d/%02d/%04d,%02d:%02d:%02d.%06d", rtc.day, rtc.month,rtc.year+2000,  rtc.hour, rtc.min, rtc.ms/1000,  (rtc.ms%1000)*1000);

	ts.tv_nsec +=TIME_WAVE_PRE;
	if(ts.tv_nsec >= 1000000000)
	{
	    ts.tv_sec  += 1;
	    ts.tv_nsec -= 1000000000;
	}	

	timespec_to_rtc(ts,  &rtc, 0);
	sprintf(prcd->f_cfs.date_i.trigger_point_ime, "%02d/%02d/%04d,%02d:%02d:%02d.%06d", rtc.day, rtc.month,rtc.year+2000,  rtc.hour, rtc.min, rtc.ms/1000,  (rtc.ms%1000)*1000);
	if(g_wave_filetype==0)
	{
	strcpy(prcd->f_cfs.ft,"ASCII");
	}
	else
	{
		strcpy(prcd->f_cfs.ft,"BINARY");
	}
	prcd->f_cfs.timemult[0] = '1'; 
	
	return 0;
}

#ifdef LINUX_KERNEL_APP
int rcd_init(void)
{
	memset(&g_rcd,0,sizeof(g_rcd));

	//创建目录。如果目录已经存在，就不会再创建
	rt_file_mkdir(RCD_FILE_PATH);
	rt_file_mkdir(RCD_XDL_FILE_PATH);
	#ifdef DFTU_LINUX_ZX
	rt_file_mkdir(RCD_BACKUP_PATH);
	#endif

	//获取录波序号
	_rcd_get_waveno();

	// 登记主循环软中断
	rt_sirq_register(RT_SOFT_IRQ_RCD,_rcd_soft_isr,"rcd_soft_isr");

	// 运行应用录波线程
	g_ts_rcd = kthread_run(_rcd_thread,NULL,"rcd_thread");
	if(IS_ERR(g_ts_rcd))
	{
		printk("ts=%p\r\n",g_ts_rcd);
		g_ts_rcd = NULL;
		return -1;
	}

	// 设置调度策略和优先级，最高
	{
		struct sched_param sp;
		sp.sched_priority = 7;
		sched_setscheduler(g_ts_rcd,SCHED_FIFO,&sp);
	}

		// 写录波文件线程
	g_ts_rcd_writefile = kthread_run(_rcd_writefile_thread,NULL,"rcd_write");
	if(IS_ERR(g_ts_rcd_writefile))
	{
		printk("ts=%p\r\n",g_ts_rcd_writefile);
		g_ts_rcd_writefile = NULL;
		return -1;
	}

	// 设置调度策略和优先级
	{
		struct sched_param sp;
		sp.sched_priority = 14;
		sched_setscheduler(g_ts_rcd_writefile,SCHED_FIFO,&sp);
	}


	g_rcd_init = 1;

	return 0;
}
#else
//linux
int rcd_init(void)
{

	int ret;

	memset(&g_rcd,0,sizeof(g_rcd));

	//创建目录。如果目录已经存在，就不会再创建
	rt_file_mkdir(RCD_FILE_PATH);
	rt_file_mkdir(RCD_XDL_FILE_PATH);
	#ifdef DFTU_LINUX_ZX
	rt_file_mkdir(RCD_BACKUP_PATH);
	#endif

	//获取录波序号
	_rcd_get_waveno();

	// 登记主循环软中断
	//rt_sirq_register(RT_SOFT_IRQ_RCD,_rcd_soft_isr,"rcd_soft_isr");

	pthread_condattr_init(&attr);												  
	pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);							  
	pthread_cond_init(&g_cond, &attr);


	ret = pthread_create(&_rcd_thread_tid, NULL, (void *)_rcd_thread, NULL);
	if(ret)
	{
		rt_printf("ret = %d, err = %s\r\n", ret, strerror(ret));
		_rcd_thread_tid = 0;
		return ret;
	}

	ret = pthread_create(&_rcd_writefile_tid, NULL, (void *)_rcd_writefile_thread, NULL);
	if(ret)
	{
		rt_printf("ret = %d, err = %s\r\n", ret, strerror(ret));
		_rcd_writefile_tid = 0;
		return ret;
	}	

	g_rcd_init = 1;

	return 0;
}

#endif

#ifdef LINUX_KERNEL_APP
int rcd_exit(void)
{
	u32 sw;
	//int i;
	struct rcd *prcd;
	
	rt_sirq_unregister(RT_SOFT_IRQ_RCD);

	if(g_ts_rcd != NULL)
	{
		wake_up(&g_wq_rcd);
		kthread_stop(g_ts_rcd);
	}

	if(g_ts_rcd_writefile != NULL)
	{
		//wake_up(&g_wq_rcd);
		kthread_stop(g_ts_rcd_writefile);
		//g_ts_rcd_writefile = NULL;
	}	

	for(sw=0;sw<=RCD_MAX_CNT;sw++)
	{
		prcd = &g_rcd[sw];
		
		_rcd_close_wave(prcd);
		_rcd_uninit_wave(prcd);
			
	}

	return 0;
}
#else
//linux
int rcd_exit(void)
{
	u32 sw;
	//int i;
	struct rcd *prcd;

	g_rcd_exit_flag = 1;
	g_rcd_writefile_exit_flag = 1;
	// rt_sirq_unregister(RT_SOFT_IRQ_RCD);

	pthread_mutex_lock(&g_mutex);
	/*唤醒*/
	pthread_cond_signal(&g_cond);
	pthread_mutex_unlock(&g_mutex);

	for(sw=0;sw<=RCD_MAX_CNT;sw++)
	{
		prcd = &g_rcd[sw];
		
		_rcd_close_wave(prcd);
		_rcd_uninit_wave(prcd);
			
	}



	pthread_join(_rcd_writefile_tid, NULL);
	pthread_join(_rcd_thread_tid, NULL);

	pthread_mutex_destroy(&g_mutex);
 	pthread_cond_destroy(&g_cond);

	return 0;
}

#endif


int rcd_start(u32 sw, u32 type,u32 waves)
{
	uint32_t flags;
	struct timespec ts;
	u32 dt;
	int i_head ;
	struct rcd *prcd;

	// 检查参数
	if(sw > SWITCH_NUM_MAX)
	{
		return -1;
	}

	// 没有初始化好
	if(g_rcd_init == 0)
	{
		return -2;
	}
	
	//过滤录波类型,如果是零流突变，必录
	if(type >= RECORD_TYPE_NUM)
	{
		return -3;
	}
	if(g_rcd_type_enable[type] == 0)
	{
	#ifdef XDL_ZT
		TSETSW *pSet = &pRunSet->tSwSet[sw];

		if((BH_ALL_EN(sw)) == 0)
		{
			return -4;
		}

		if((type == RECORD_TYPE_LLTB && pSet->bTT_xdlqd == XDL_QD_I0)
		|| (type == RECORD_TYPE_LXDY && pSet->bTT_xdlqd == XDL_QD_U0))
		{
		}
		else
		{
			return -41;
		}
	#else
		//if((BH_ALL_EN(sw)) == 0)
		{
			return -4;
		}
	#endif
	}

	if(g_sw_ac_num[sw]==0)
	{
		rt_printf("开关%02d没有配置模拟量!\r\n",sw);
		return -5;	
	}	

	// 获取一个录波的数据结构
	i_head = -1;
	rt_irq_save(flags);
	if(((rcd_head+1)&(RCD_MAX_CNT-1)) != rcd_tail)
	{
		i_head=rcd_head;
		rcd_head = ((rcd_head+1)&(RCD_MAX_CNT-1));
	}
	rt_irq_restore(flags);

	if(i_head == -1)
	{
		rt_printf("录波缓存已满(sw=%02d,type=%d)!\r\n",sw,type);
		return -6;
	}

	prcd  = &g_rcd[i_head];
	prcd->state = RCD_ST_START_0;

	// 最大录1000个周波，20S，约4M数据
	if(waves > 1000)
	{
		waves = 1000;
	}

	
	// 初始化数据
	prcd->type=type;
	//置录波类型标志
	//prcd->rcd_working=1;
	prcd->sw = sw;
	
	// 获取时间点，通过关中断保证时间的一致性
	rt_irq_save(flags);
#ifdef CPU_FUXI
	// ts=ts_adc_dots[g_adc_dots_index];
	// 目前时间戳没有通过共享内存记录r核的时间，此处采用gps_get_time，但是现在采样点5ms更新一次，因此此处的时间最大可能出现5ms误差
	gps_get_time(&ts); 
#else
	gps_get_time(&ts);
#endif	
	dt=g_adc_dots_count; 
	rt_irq_restore(flags);


	// 得到第一个采样点的时刻
	if(ts.tv_nsec < TIME_WAVE_PRE)
	{
		ts.tv_sec--;
		ts.tv_nsec += NSEC_PER_SEC;
	}
	ts.tv_nsec -= TIME_WAVE_PRE;

	prcd->ts_begin = ts;
	
	// 采样点相关初始化
	prcd->dt_begin = dt - CFG_ADC_DOTS_PER_PERIOD*6; // 前6个周波的位置
	prcd->dt_cur = prcd->dt_begin;
	prcd->dt_end   = dt + CFG_ADC_DOTS_PER_PERIOD*waves;   //启动后waves个周波

	// 初始标志
	prcd->fd_cfg = -1;
	prcd->fd_dat = -1;
	prcd->state = RCD_ST_START_1;
	//g_rcd_working |= 1<<sw;  //录波已经启动	

//	rt_printf("启动录波(sw=%02d,type=%d)!\r\n",sw,type);
#ifdef LINUX_KERNEL_APP
	rt_sirq_force(RT_SOFT_IRQ_RCD);
#else
	wq_rcd();
#endif
	return 0;
}

//初始化小电流模拟通道
int rcd_init_A_xdl(struct rcd *prcd)
{
	int i=0;
//	u32 type=0;

	//u32 sw = SWITCH_NUM_MAX;


		    
	for(i=0;i<prcd->f_cfs.tt.A;i++)
	{
		prcd->f_cfs.tt_a[i].An = i+1;
	#ifdef XDL_ZT	
		sprintf(prcd->f_cfs.tt_a[i].ch_id,"%s" ,xdl_get_chan_name(i));
	#endif
		//sprintf(g_rcd[sw].f_cfs.tt_a[i].Ph, "%s", pabc);
		strcpy(prcd->f_cfs.tt_a[i].Uu," ");
		


	
		prcd->f_cfs.tt_a[i].a =1.0;
		prcd->f_cfs.tt_a[i].b = 0;
		prcd->f_cfs.tt_a[i].skew = 0;
		prcd->f_cfs.tt_a[i].max = 32767;
		prcd->f_cfs.tt_a[i].min= -32767;
		prcd->f_cfs.tt_a[i].primary = 1.0;
		prcd->f_cfs.tt_a[i].secondary= 1.0;
		prcd->f_cfs.tt_a[i].ps[0]='S';
		prcd->f_cfs.tt_a[i].ps[1]=0;
	

		//rt_printf("%d,%s,%s,%s,", g_rcd[sw].f_cfs.tt_a[i].An, g_rcd[sw].f_cfs.tt_a[i].ch_id, g_rcd[sw].f_cfs.tt_a[i].Ph, g_rcd[sw].f_cfs.tt_a[i].Uu );
		//rt_printf("%f,%f,%f,%d,%d,", g_rcd[sw].f_cfs.tt_a[i].a, g_rcd[sw].f_cfs.tt_a[i].b, g_rcd[sw].f_cfs.tt_a[i].skew, g_rcd[sw].f_cfs.tt_a[i].min, g_rcd[sw].f_cfs.tt_a[i].max);

		//rt_printf("%f,%f,%s\r\n", g_rcd[sw].f_cfs.tt_a[i].primary, g_rcd[sw].f_cfs.tt_a[i].secondary, g_rcd[sw].f_cfs.tt_a[i].ps);
		
	}

	return 0;
}


int rcd_init_channel_xdl(struct rcd *prcd)
{

	int cnt = 0;
	int pub_cnt = 0;
	struct rtc_time_t   rtc;
	struct timespec ts;	
	//u32 sw = SWITCH_NUM_MAX;
	char tmp_buf[64];
//	u32 type=0;

	memset(tmp_buf, 0, sizeof(tmp_buf));
	set_get_fixed_arg(FIXED_SET_MAU, tmp_buf, sizeof(tmp_buf));
	sprintf(prcd->f_cfs.srr.station_name, "%s ", tmp_buf);
	memset(tmp_buf, 0, sizeof(tmp_buf));
	set_get_fixed_arg(FIXED_SET_TPE, tmp_buf, sizeof(tmp_buf));
	strcat(prcd->f_cfs.srr.station_name, tmp_buf);
	sprintf(prcd->f_cfs.srr.rec_dev_id, "%03d", 1);
	sprintf(prcd->f_cfs.srr.rev_year, "%d", 1999);
	
	//rt_printf("sw=%d\r\n", sw);
#ifdef XDL_ZT		
	cnt = xdl_get_chan_cnt();
#endif
	prcd->f_cfs.tt_a_cnt = cnt;
	prcd->f_cfs.tt_d_cnt = 0;
	
	
	if(cnt == 0)
	{
		return -1;
	}


	
	{
		//模拟通道
		prcd->f_cfs.tt_a = rt_malloc((cnt+pub_cnt)*sizeof(struct cfg_file_TT_A  ));
		if(!prcd->f_cfs.tt_a)
		{
			return -1;
		}
		memset(prcd->f_cfs.tt_a , 0, (cnt+pub_cnt) *sizeof(struct cfg_file_TT_A ));

		//模拟通道对应的配置索引
		prcd->f_cfs.tt_a_index = rt_malloc((cnt+pub_cnt) *sizeof(int));
		if(!prcd->f_cfs.tt_a_index)
		{
			rt_free(prcd->f_cfs.tt_a);
			return -1;
		}
	}	

	//模拟通道数	
	prcd->f_cfs.tt.A = prcd->f_cfs.tt_a_cnt ;
	//开关量通道数
	prcd->f_cfs.tt.D = prcd->f_cfs.tt_d_cnt;

	//rt_printf("%s,%s,%s\r\n", g_rcd[sw].f_cfs.srr.station_name,  g_rcd[sw].f_cfs.srr.rec_dev_id,  g_rcd[sw].f_cfs.srr.rev_year);
	//rt_printf("TT:%dA,%dD\r\n", g_rcd[sw].f_cfs.tt.A, g_rcd[sw].f_cfs.tt.D);
	rcd_init_A_xdl(prcd);
	prcd->f_cfs.Lf = freq_get(0);
	prcd->f_cfs.si.nrates = 1;
	if((g_freq < 45.0) || (g_freq > 55.0) )
	{
	prcd->f_cfs.si.samp = 6400;
	}
	else
	{
		prcd->f_cfs.si.samp =  g_freq * CFG_ADC_DOTS_PER_PERIOD*ADC_REC_SAMPLE_RATE; 	
	}	
	prcd->samp_t = 1000000/prcd->f_cfs.si.samp;
	prcd->f_cfs.si.endsamp = XDL_SAMPLE_LEN;

	ts = prcd->ts_begin;
	timespec_to_rtc(ts,  &rtc, 0);
	sprintf(prcd->f_cfs.date_i.firsttime, "%02d/%02d/%04d,%02d:%02d:%02d.%06d", rtc.day, rtc.month,rtc.year+2000,  rtc.hour, rtc.min, rtc.ms/1000,  (rtc.ms%1000)*1000);

	ts.tv_nsec +=TIME_WAVE_PRE;
	if(ts.tv_nsec >= 1000000000)
	{
	    ts.tv_sec  += 1;
	    ts.tv_nsec -= 1000000000;
	}	

	timespec_to_rtc(ts,  &rtc, 0);
	sprintf(prcd->f_cfs.date_i.trigger_point_ime, "%02d/%02d/%04d,%02d:%02d:%02d.%06", rtc.day, rtc.month,rtc.year+2000,  rtc.hour, rtc.min, rtc.ms/1000,  (rtc.ms%1000)*1000);
	if(g_wave_filetype==0)
	{
	strcpy(prcd->f_cfs.ft,"ASCII");
	}
	else
	{
		strcpy(prcd->f_cfs.ft,"BINARY");
	}
	prcd->f_cfs.timemult[0] = '1'; 
	
	return 0;
}


int _rcd_open_xdl_cfg(char *name,struct rcd *prcd, struct timespec *ts)
{
	int ret = 0;
//	int sw = RCD_XDL_NO;
//	u32 type = 0;
	u32 xdl_sw = prcd->sw;

	prcd->ts_begin = *ts;

	if(name)
	{
		sprintf(prcd->tmp_cfg, "/tmp/xdl_%s_%d.cfg", name,(int)xdl_sw);
	}
	else
	{
		sprintf(prcd->tmp_cfg, "/tmp/xdl_wave_%d.cfg", (int)xdl_sw);
	}
	

	//打开文件
	prcd->fd_cfg = sys_open(prcd->tmp_cfg,  O_CREAT|O_RDWR|O_TRUNC , 0777);

	if(prcd->fd_cfg < 0)
	{
		rt_printf("%s:sys_open(%s) error\n",__func__, prcd->tmp_cfg);
		return -1;
	}


	ret=rcd_init_channel_xdl(prcd);	
	

	//分配内存,用于缓存.cfg文件内容.
	prcd->pcfg_mem = rt_malloc(RCD_CFG_FILE_SIZE);

	if(!prcd->pcfg_mem)
	{
		rt_printf("%s: rt_malloc(RCD_CFG_FILE_SIZE) error\r\n", __func__);
		return -1;
	}

	
	//最大缓存文件大小
	prcd->pcfg_mem_size = RCD_CFG_FILE_SIZE;
	prcd->pcfg_mem_pos = 0;
		
	return  0;
}

int _rcd_close_xdl_cfg(struct rcd *prcd)
{
	//u32 sw = RCD_XDL_NO;
	//u32 type = 0;

	if(prcd->fd_cfg >= 0)
	{
		sys_close(prcd->fd_cfg);
		prcd->fd_cfg = -1;
	}

	if(prcd->pcfg_mem)
	{
		rt_free(prcd->pcfg_mem);
		prcd->pcfg_mem = 0;
		prcd->pcfg_mem_pos = 0;
	}

	return 0;

}

int _rcd_open_xdl_dat(char *name,struct rcd *prcd, struct timespec *ts)
{
	struct rtc_time_t   rtc;
//	int sw = RCD_XDL_NO;
//	u32 type = 0;
	u32 xdl_sw = prcd->sw;

	prcd->pdat_mem = 0;
	prcd->pdat_mem_pos = 0;
	
	
	prcd->ts_begin = *ts;
	
	
	timespec_to_rtc(*ts,  &rtc, 0);

	if(name)
	{ 
		sprintf(prcd->tmp_dat, "/tmp/xdl_%s_%d.dat", name,(int)xdl_sw);
	}
	else
	{
		sprintf(prcd->tmp_dat, "/tmp/xdl_wave_%d.dat", (int)xdl_sw);
	}
	
	
	prcd->fd_dat = sys_open(prcd->tmp_dat, O_CREAT|O_RDWR|O_TRUNC , 0777);	

	if(prcd->fd_dat < 0)
	{
		rt_printf("%s:sys_open(%s) error\n",__func__, prcd->tmp_dat);
		return -1;
	}

	memset(&prcd->f_dfs, 0, sizeof(prcd->f_dfs));
	
	//分配内存，用于缓存每个模拟通道数据
	if(!prcd->pAn)
	{
		//缓存个数
		prcd->pAn_size = prcd->f_cfs.tt_a_cnt *  XDL_SAMPLE_LEN;
		//序号
		prcd->pAn_no = 0;
		//分配内存
		prcd->pAn = rt_malloc(prcd->pAn_size*sizeof(int));	
		if(!prcd->pAn)
		{
			rt_printf("%s: rt_malloc(pAn) error\r\n", __func__);	
			return -1;
		}		
		
	}

	//分配内存，用于缓存每个开关量通道数据
	if(!prcd->pDn)
	{
		//缓存个数
		prcd->pDn_size = prcd->f_cfs.tt_d_cnt *  XDL_SAMPLE_LEN;
		//序号
		prcd->pDn_no = 0;
		//分配内存
		prcd->pDn = rt_malloc(prcd->pDn_size*sizeof(u8));	
		if(!prcd->pDn)
		{
			rt_printf("%s: rt_malloc(pDn) error\r\n", __func__);	
			return -1;
		}		
	}

	//分配内存，用于缓存一条记录
	if(!prcd->pdat_mem)
	{
		//一条记录最大字节数
		prcd->pdat_mem_size = (prcd->f_cfs.tt_a_cnt*sizeof(s16)+8) *  XDL_SAMPLE_LEN;
		//位置
		prcd->pdat_mem_pos = 0;	
		//分配内存
		prcd->pdat_mem = rt_malloc(prcd->pdat_mem_size);	
		if(!prcd->pdat_mem)
		{
			rt_printf("%s: rt_malloc(%d) error\r\n", __func__, prcd->pdat_mem_size);	
			return -1;
		}
		
		
		
	}	
	
	return 0;
}

int _rcd_close_xdl_dat(struct rcd *prcd)
{
	//u32 sw = RCD_XDL_NO;
	//u32 type = 0;
	
	if(prcd->fd_dat >= 0)
	{
		sys_close(prcd->fd_dat);
		prcd->fd_dat = -1;
	}


	if(prcd->pAn)
	{
		rt_free(prcd->pAn);	
		prcd->pAn = 0;
		
	}

	if(prcd->pDn)
	{
		rt_free(prcd->pDn);	
		prcd->pDn = 0;
		
	}

	if(prcd->pdat_mem)
	{
		rt_free(prcd->pdat_mem);	
		prcd->pdat_mem = 0;
		prcd->pdat_mem_size=  0;
		prcd->pdat_mem_pos = 0;	
		
	}	

	return 0;
}



void _rcd_xdl_save(struct rcd *prcd)
{

	//int sw = RCD_XDL_NO;
	int i,j;
	int ret;
#ifdef XDL_ZT
	int pAn_no=0;
#endif
	//u32 type = 0;

	rcd_write_cfg(prcd);

	prcd->pAn_no = 0;
	
	for(i=0;i<XDL_SAMPLE_LEN;i++)
	{
		for(j=0; j< prcd->f_cfs.tt_a_cnt; j++)
		{
		#ifdef XDL_ZT
			prcd->pAn[pAn_no++] = xdl_rcd_a(j, i);
		#endif
			
		
			//index = g_rcd[sw].f_cfs.tt_a_index[i];
			//channel=equ_get_ac_channel(g_equ_config_ac[index].slot, g_equ_config_ac[index].index);
			//if(channel < 0 || channel >= CFG_ADC_CHANNEL )
	 		{
	 			//continue;
	 		}
			
			//记录每个通道的数据
			//g_rcd[sw].pAn[g_rcd[sw].pAn_no++] =  g_adc_dots_rec[cur][channel]; 
		}
		rcd_write_dat(prcd);
	}
	

	ret = sys_write(prcd->fd_dat, prcd->pdat_mem, prcd->pdat_mem_pos);
	if(ret!=prcd->pdat_mem_pos)
	{
		rt_printf("%s: sys_write(%d)=%d error\r\n", __func__, prcd->pdat_mem_pos, ret);	
	}
	prcd->pdat_mem_pos = 0;

	
}

int rcd_start_xdl(char *name,int sw,char **chn_name,int chn_num,int chn_length,struct timespec *ts)
{
	int ret;
//	u32 type = 0;
	struct rcd *prcd = &g_rcd_xdl[0];
	
	prcd->fd_cfg = -1;
	prcd->fd_dat = -1;
	prcd->sw = sw;
	
	ret = _rcd_open_xdl_cfg(name,prcd, ts);
	if(ret < 0)
	{
		goto RET;
	}
	ret = _rcd_open_xdl_dat(name,prcd, ts);
	if(ret < 0)
	{
		goto RET;
	}
	
	_rcd_xdl_save(prcd);

RET:
	_rcd_close_xdl_dat(prcd);
	_rcd_close_xdl_cfg(prcd);
	return 0;
}



// 判断录波是否已完成
int rcd_check_ok(u32 sw)
{
//	u32 type = 0;
	
	//if (g_rcd_working &(1<<sw))
	//if(g_rcd[sw][type].rcd_working)
	if(rcd_sd_flag==0)
	{
		return 0;
	}

	rcd_sd_flag = 0;
	return 1;
}

/******************************************************************************
函数名称：	get_rcd_list_name
函数版本：	01.01
创建作者:	sunxi
创建日期：	2013-08-08
函数说明：	获取录波文件的名称
参数说明：
返回值：	
	0：		成功
	其它：	失败
修改记录：	
*/
int rcd_get_list_name(void)
{
#ifdef CPU_AM335X
	char* m_path = "/app/335x_m";
#else
	char* m_path = "/app/m";
#endif
	u32 len;
	int i, loop;
	u8 *buf;
	char *envp[] = { NULL };

	struct file * pfile;
	loff_t pos;

	char *cmd_ls[] = {m_path,"ls", RCD_FILE_PATH, "/tmp/rcd_list.txt",  NULL};
	
#ifdef CPU_FUXI
	char tmp[128];
	memset(tmp,0,sizeof(tmp));
	sprintf(tmp," ls %s > %s",RCD_FILE_PATH,"/tmp/rcd_list.txt");
	system(tmp);
#else	
	//调用shell脚本,生成文件列表filelist.txt
	call_usermodehelper(m_path,  cmd_ls,  envp,  UMH_WAIT_PROC);
#endif

	// 打开文件
	pfile = rt_file_open("/tmp/rcd_list.txt",O_RDONLY ,0);
	if(IS_ERR(pfile))
	{
		return -1;
	}

	// 得到文件长度
	len = rt_file_getfile_size(pfile);
	if(len <= 0)
	{
		rt_file_close(pfile,0);
		return -11;
	}
	
	// 分配内存
	buf = rt_malloc(len);
	if((buf) == NULL)
	{
		rt_file_close(pfile,0);
		return -2; 	
	}

	// 读出内容
	pos = 0;
	if(rt_file_read(pfile,buf,len,&pos) != len)
	{
		rt_file_close(pfile,0);
		rt_free(buf);
		return -3;
	}

	// 关闭文件
	rt_file_close(pfile,0);

	// 检查文件长度
	if(len > 37*RECORD_FILES_MAX)
	{
		rt_free(buf);
		return -4; 	
	}

	// 拷贝名称
	loop = len/35;

	for (i=0; i<loop; i++)
	{
		memset(&wave_name[i], 0, 40);
		memcpy(&wave_name[i], &buf[i*36], 35);
	}
	
	return loop;

}
/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/
#ifdef LINUX_KERNEL_APP
int _rcd_soft_isr(int irq, void *dev_id)
{
	rt_sirq_clear(RT_SOFT_IRQ_RCD);

	g_wq_rcd_flag = 1;
	wake_up(&g_wq_rcd);

	return (int)IRQ_HANDLED;

}
#else
int _rcd_soft_isr(int irq, void *dev_id)
{
	//rt_sirq_clear(RT_SOFT_IRQ_RCD);

	//g_wq_rcd_flag = 1;
	//wake_up(&g_wq_rcd);

	pthread_mutex_lock(&g_mutex);
	/*唤醒*/
	pthread_cond_signal(&g_cond);
	pthread_mutex_unlock(&g_mutex);

	return 0;
}

void wq_rcd(void)
{
	pthread_mutex_lock(&g_mutex);
	/*唤醒*/
	pthread_cond_signal(&g_cond);
	pthread_mutex_unlock(&g_mutex);

}

#endif


//反初始化函数
void  _rcd_uninit_wave(struct rcd *prcd)
{

	//rt_printf("_rcd_uninit_wave...\r\n");

	if(prcd->f_cfs.tt_a)
	{
		rt_free(prcd->f_cfs.tt_a);
		prcd->f_cfs.tt_a = 0;
	}

	if(prcd->f_cfs.tt_a_index)
	{
		rt_free(prcd->f_cfs.tt_a_index);
		prcd->f_cfs.tt_a_index = 0;
	}

	if(prcd->f_cfs.tt_d)
	{
		rt_free(prcd->f_cfs.tt_d);
		prcd->f_cfs.tt_d = 0;
	}

	if(prcd->f_cfs.tt_d_index)
	{
		rt_free(prcd->f_cfs.tt_d_index);
		prcd->f_cfs.tt_d_index = 0;
	}	

	if(prcd->pcfg_mem)
	{
		rt_free(prcd->pcfg_mem);
		prcd->pcfg_mem = 0;
		prcd->pcfg_mem_size = 0;
		prcd->pcfg_mem_pos = 0;
	}



	if(prcd->pAn)
	{
		rt_free(prcd->pAn);	
		prcd->pAn = 0;
		
	}

	if(prcd->pDn)
	{
		rt_free(prcd->pDn);	
		prcd->pDn = 0;
		
	}

	if(prcd->pdat_mem)
	{
		rt_free(prcd->pdat_mem);	
		prcd->pdat_mem = 0;
		prcd->pdat_mem_size=  0;
		prcd->pdat_mem_pos = 0;	
		
	}

}

int  _rcd_init_wave(struct rcd *prcd)
{
	struct rtc_time_t   rtc;
	struct timespec ts;
	int ret=0;
	u32 sw= prcd->sw;
//	u32 type = prcd->type;
	
	ts = prcd->ts_begin;
	ts.tv_nsec +=TIME_WAVE_PRE;
	if(ts.tv_nsec >= 1000000000)
	{
	    ts.tv_sec  += 1;
	    ts.tv_nsec -= 1000000000;
	}	
	
	timespec_to_rtc(ts,  &rtc, 0);

	if(sw==SWITCH_NUM_MAX)
	{
		sprintf( prcd->tmp_cfg, "/tmp/ALL_wave.cfg");
	}
	else
	{
#ifdef RCD_STRAN_S
		sprintf( prcd->tmp_cfg, "/tmp/BAY%02d_%04d_%04d%02d%02d_%02d%02d%02d_%03d.cfg",tRunPara.byAddr,g_new_waveno[sw] ,  rtc.year+2000, rtc.month, rtc.day, rtc.hour, rtc.min, rtc.ms/1000,  rtc.ms%1000);
#else
		sprintf( prcd->tmp_cfg, "/tmp/BAY%02d_%04d_%04d%02d%02d_%02d%02d%02d_%03d.cfg",sw+1,g_new_waveno[sw] ,  rtc.year+2000, rtc.month, rtc.day, rtc.hour, rtc.min, rtc.ms/1000,  rtc.ms%1000);
#endif
	}	

	if(sw==SWITCH_NUM_MAX)
	{
		ret=rcd_init_channel_all(prcd);	

	}
	else
	{
		ret=rcd_init_channel(prcd);	
	}

	if(ret!=0)
	{
		
		return -1;
	}	

	//分配内存,用于缓存.cfg文件内容.
	 prcd->pcfg_mem = rt_malloc(RCD_CFG_FILE_SIZE);

	if(! prcd->pcfg_mem)
	{
		rt_printf("%s: rt_malloc(RCD_CFG_FILE_SIZE) error\r\n", __func__);
		return -1;
	}
	//最大缓存文件大小
	 prcd->pcfg_mem_size = RCD_CFG_FILE_SIZE;
	 prcd->pcfg_mem_pos = 0;



	 prcd->pdat_mem = 0;
	 prcd->pdat_mem_pos = 0;
	

	if(sw==SWITCH_NUM_MAX)
	{
		 sprintf(prcd->tmp_dat, "/tmp/ALL_wave.dat");
	}
	else
	{
#ifdef RCD_STRAN_S		
		 sprintf(prcd->tmp_dat, "/tmp/BAY%02d_%04d_%04d%02d%02d_%02d%02d%02d_%03d.dat",tRunPara.byAddr, g_new_waveno[sw] , rtc.year+2000, rtc.month, rtc.day, rtc.hour, rtc.min, rtc.ms/1000,  rtc.ms%1000);
#else
		 sprintf(prcd->tmp_dat, "/tmp/BAY%02d_%04d_%04d%02d%02d_%02d%02d%02d_%03d.dat",sw+1, g_new_waveno[sw] , rtc.year+2000, rtc.month, rtc.day, rtc.hour, rtc.min, rtc.ms/1000,  rtc.ms%1000);
#endif
	}


	memset(& prcd->f_dfs, 0, sizeof( prcd->f_dfs));
	
	//分配内存，用于缓存每个模拟通道数据
	if(! prcd->pAn)
	{
		//缓存个数
		 prcd->pAn_size = prcd->f_cfs.tt_a_cnt *  ( prcd->dt_end -  prcd->dt_begin) * ADC_REC_SAMPLE_RATE;
		//序号
		 prcd->pAn_no = 0;
		//分配内存
		 prcd->pAn = rt_malloc( prcd->pAn_size*sizeof(int));	
		if(! prcd->pAn)
		{
			rt_printf("%s: rt_malloc(pAn) error\r\n", __func__);	
			return -1;
		}		
		
	}

	//分配内存，用于缓存每个开关量通道数据
	if(! prcd->pDn)
	{
		//缓存个数
		 prcd->pDn_size =  prcd->f_cfs.tt_d_cnt *  ( prcd->dt_end -  prcd->dt_begin) * ADC_REC_SAMPLE_RATE;
		//序号
		 prcd->pDn_no = 0;
		//分配内存
		 prcd->pDn = rt_malloc( prcd->pDn_size*sizeof(u8));	
		if(! prcd->pDn)
		{
			rt_printf("%s: rt_malloc(pDn) error\r\n", __func__);	
			return -1;
		}		
	}

	//分配内存，用于缓存一条记录
	if(! prcd->pdat_mem)
	{
		//一条记录最大字节数
		 prcd->pdat_mem_size = RCD_LINE_BUF_SIZE;
		//位置
		 prcd->pdat_mem_pos = 0;	
		//分配内存
		 prcd->pdat_mem = rt_malloc( prcd->pdat_mem_size);	
		if(! prcd->pdat_mem)
		{
			rt_printf("%s: rt_malloc(%d) error\r\n", __func__,  prcd->pdat_mem_size);	
			return -1;
		}
		
		
		
	}	
		
	if(g_new_waveno[sw]  >= RCD_WAVE_MAX_NO)
	{
		g_new_waveno[sw]  = 1;
	}
	else
	{
		g_new_waveno[sw]++;
	}		
	return 0;
	
}

int _rcd_open_cfg_wave(struct rcd *prcd)
{
	if(prcd->fd_cfg >= 0)
	{
		return 0;	
	}

	//打开文件
	prcd->fd_cfg = sys_open(prcd->tmp_cfg,  O_CREAT|O_RDWR|O_TRUNC , 0777);

	if(prcd->fd_cfg < 0)
	{
		rt_printf("%s:sys_open(%s) error\n",__func__, prcd->tmp_cfg);
		return -1;
	}

	return  0;
}

int _rcd_close_cfg_wave(struct rcd *prcd)
{

	if(prcd->fd_cfg >= 0)
	{
		sys_close(prcd->fd_cfg);
		prcd->fd_cfg = -1;
	}


	return 0;

}
int _rcd_open_dat_wave(struct rcd *prcd)
{
	//文件已经打开，返回
	if(prcd->fd_dat >= 0)
	{
		return 0;
	}
	
	prcd->fd_dat = sys_open(prcd->tmp_dat, O_CREAT|O_RDWR|O_TRUNC , 0777);	

	if(prcd->fd_dat < 0)
	{
		rt_printf("%s:sys_open(%s) error\n",__func__, prcd->tmp_dat);
		return -1;
	}

	return 0;
}

int _rcd_close_dat_wave(struct rcd *prcd)
{
	if(prcd->fd_dat >= 0)
	{
		sys_close(prcd->fd_dat);
		prcd->fd_dat = -1;
	}


	return 0;
}


//打开创建录波文件
int _rcd_open_wave(struct rcd *prcd)
{
	 
	int ret = 0;	

	ret = _rcd_open_cfg_wave(prcd);
	if(ret !=0 )
	{
		return -1;
	}
	 
	ret = _rcd_open_dat_wave(prcd);
	if(ret !=0 )
	{
		return -1;
	}


	
	return 0;
	
}

int _rcd_close_wave(struct rcd *prcd)
{

	_rcd_close_cfg_wave(prcd);
	_rcd_close_dat_wave(prcd);

	return 0;
}


#if 0
int _rcd_open(u32 sw)
{
	static struct rcd_file_head rfh;
	static struct rcd_ac rac;
	
	int i;
	float f;

	// 打开文件
	g_rcd[sw].f_handle = rt_file_open(RCD_FILE_NAME,O_CREAT|O_RDWR|O_TRUNC ,0);
	if(IS_ERR(g_rcd[sw].f_handle))
	{
		return -1;
	}

	memset(&rfh,0,sizeof(rfh));

	// 文件签名和版本
	rfh.cfh.signature = SIG_RECORD_FILE;
	rfh.cfh.version = 1;

	//文件头
	strcpy(rfh.equ_name,EQUIP_NAME_STRING);
	sprintf(rfh.version,"V%d.%02d.%02d",(VER_NUM>>16)&0XFF,(VER_NUM>>8)&0XFF,VER_NUM&0XFF);
	rfh.ts_begin = g_rcd[sw].ts_begin;
	rfh.type = g_rcd[sw].type;
	rfh.dots_per_period = CFG_ADC_DOTS_PER_PERIOD;

	//AC
	rfh.ac_addr = sizeof(rfh);
	rfh.ac_num = g_equ_config->ac_num;

	//DI
	rfh.di_addr = rfh.ac_addr + sizeof(struct rcd_ac)*rfh.ac_num;
	rfh.di_num = 0;
	
	// DO
	rfh.do_addr = rfh.di_addr + sizeof(struct rcd_di)*rfh.di_num;
	rfh.do_num = 0;

	// 采样点
	rfh.dot_addr = rfh.do_addr + sizeof(struct rcd_do)*rfh.do_num;
	rfh.dot_num = g_rcd[sw].dt_end - g_rcd[sw].dt_begin;

	// 将文件头写入文件
	g_rcd[sw].f_offset = 0;
	rt_file_write(g_rcd[sw].f_handle,(char *)&rfh,sizeof(rfh),&g_rcd[sw].f_offset);

	// AC描述区
	// 交流测量量
	for(i=0; i< g_equ_config->ac_num; i++)
	{
		strcpy(rac.name,g_equ_config_ac[i].name);
		
		rac.slot = g_equ_config_ac[i].slot;
		rac.index = g_equ_config_ac[i].index;
		rac.owner = g_equ_config_ac[i].owner;
		rac.type = g_equ_config_ac[i].type;
		rac.is_ct_inverse = g_equ_config_ac[i].is_ct_inverse;
		if(rac.type == 0)
		{
			rac.is_not_owner = 1;
		}
		else
		{
			rac.is_not_owner = 0;
		}
		
		rac.channel =  equ_get_ac_channel(g_equ_config_ac[i].slot,g_equ_config_ac[i].index);
			
		// 系数
		rac.factor_e_k = (float)(factor_e_k(g_equ_config_ac[i].scale));
		factor_e_c_get(g_equ_config_ac[i].slot,g_equ_config_ac[i].index,&f);
		rac.factor_e_c= f;
		rac.factor_p_k = (float)(factor_p_k(rac.channel));
		factor_p_c_get(g_equ_config_ac[i].slot,g_equ_config_ac[i].index,&f);
		rac.factor_p_c = f;

		g_rcd[sw].f_offset = rfh.ac_addr + i*sizeof(rac);
		rt_file_write(g_rcd[sw].f_handle,(char *)&rac,sizeof(rac),&g_rcd[sw].f_offset);
	}
	
	// DI描述区
	for(i=0; i<rfh.di_num; i++)
	{
	}
	
	// DO描述区
	for(i=0; i<rfh.do_num; i++)
	{
	}

	// 定位采样点的文件位置
	g_rcd[sw].f_offset = rfh.dot_addr;
	
	return 0;
}

#endif
int _rcd_save(struct rcd *prcd)
{
	uint64_t us0;
	
	int i,loop;
	u32 dt_end; 
	int index=0;
	u32 sw=prcd->sw;
//	u32 type=prcd->type;
	
	// 检查是否覆盖
	if((int)(g_adc_dots_count - prcd->dt_cur) > (ADC_REC_DOTS_CHANNEL/ADC_REC_SAMPLE_RATE - 8))
	{
		rt_printf("_rcd_save overrun(%d):g_adc_dots_count=%d,dt_begin=%d,dt_cur=%d,dt_end=%d.\r\n",
				sw,
				g_adc_dots_count,
				prcd->dt_begin,
				prcd->dt_cur,
				prcd->dt_end);
		_rcd_close_wave(prcd);
		
		return -1;
	}

	us0 = ustimer_get_origin();
	
	// 由于遥信需要防抖处理后才能送到,所有需要延迟处理,目前延迟15个周波,300ms.
	dt_end = g_adc_dots_count - CFG_ADC_DOTS_PER_PERIOD*15;
	dt_end = ((int)(prcd->dt_end - dt_end) > 0) ? dt_end : prcd->dt_end;
	
	while((int)(dt_end - prcd->dt_cur) > 0)
	{
		for(loop=0;loop<ADC_REC_SAMPLE_RATE;loop++)
		{
			u32 cur = (prcd->dt_cur*ADC_REC_SAMPLE_RATE+loop) & ADC_REC_DOTS_MASK;
			for(i=0; i< prcd->f_cfs.tt_a_cnt; i++)
			{
				
				//记录每个通道的数据
				prcd->pAn[prcd->pAn_no++] =  g_adc_dots_rec[cur][prcd->f_cfs.chnl[i]]; 
			}
			
			for(i=0; i< prcd->f_cfs.tt_d_cnt; i++)
			{
				index = prcd->f_cfs.tt_d_index[i];
				prcd->pDn[prcd->pDn_no++] =(u8)dido_di_is_on_ts(g_equ_config_di[index].slot, g_equ_config_di[index].index, prcd->dt_cur);	
			}
			 
		}
		
		prcd->dt_cur++;
	}
	rt_stat_other_in(6,ustimer_get_duration(us0)/USTIMER_US);

	// 根据条件启动小电流接地判断
	if(prcd->dt_cur == prcd->dt_end)
	{
		// 如果没有投入小电流接地，直接返回
		if((BH_ALL_EN(sw)) == 0)
		{
			return 0;
		}
	#ifdef XDL_ZT	
		{
			TSETSW *pSet = &pRunSet->tSwSet[sw];
			// 如果录波类型和启动类型一起，调用小电流接地判断函数
			if((prcd->type == RECORD_TYPE_LLTB && pSet->bTT_xdlqd == XDL_QD_I0)
			|| (prcd->type == RECORD_TYPE_LXDY && pSet->bTT_xdlqd == XDL_QD_U0))
			{
				xdl_proc_adc(sw,prcd->dt_begin*ADC_REC_SAMPLE_RATE,&prcd->ts_begin);
			}
		}
	#endif
	}

	return 0;
}

#ifdef LINUX_KERNEL_APP
int _rcd_thread(void * unused)
{
	int tmp_tail;
	struct rcd *prcd;

	while(1)
	{
		wait_event_interruptible_timeout(g_wq_rcd,g_wq_rcd_flag,HZ/20); // 50ms
		g_wq_rcd_flag = 0;
		
		if(kthread_should_stop())
		{
			return 0;
		}

		for(tmp_tail = rcd_tail; tmp_tail != rcd_head; tmp_tail = (tmp_tail + 1) % RCD_MAX_CNT)
		{
			//得到录波数据结构指针
			prcd = &g_rcd[tmp_tail];

			switch(prcd->state )
			{
			case RCD_ST_START_1:
				//初始化录波文件需要的辅助信息
				if(_rcd_init_wave(prcd)!=0)
				{
					rt_printf("录波初始化失败(sw=%d,type=%d)!\r\n", prcd->sw, prcd->type);
					prcd->state = RCD_ST_RECORD_ERR;
				}
				else
				{
					prcd->state = RCD_ST_RECORD;
				}
				break;
			case RCD_ST_RECORD:
				//录波未完成继续录波.如果录波已经完成，但是还没有写进文件，返回
				if(prcd->dt_cur != prcd->dt_end)
				{
					if(_rcd_save(prcd)<0)
					{
						rt_printf("录波失败(sw=%d,type=%d)!\r\n", prcd->sw, prcd->type);
						prcd->state = RCD_ST_RECORD_ERR;
					}
					 
				}
				else
				{	
					prcd->state = RCD_ST_RECORD_OK;

				}
				break;		
			}
		}
	}

	return 0;
}
#else
int _rcd_thread(void * unused)
{
	int tmp_tail;
	struct rcd *prcd;
	struct timespec tv;

	prctl(PR_SET_NAME, "_rcd_thread");
	while(1)
	{
		// wait_event_interruptible_timeout(g_wq_rcd,g_wq_rcd_flag,HZ/20); // 50ms
		// g_wq_rcd_flag = 0;

		pthread_mutex_lock(&g_mutex);
		/*此处等待唤醒*/
		clock_gettime(CLOCK_MONOTONIC, &tv);                                       
		tv.tv_nsec += 50*1000*1000;// 50ms
	
		pthread_cond_timedwait(&g_cond, &g_mutex, &tv);
		
		/*唤醒成功*/
		pthread_mutex_unlock(&g_mutex);
		
		if(g_rcd_exit_flag)
		{
			return 0;
		}

		for(tmp_tail = rcd_tail; tmp_tail != rcd_head; tmp_tail = (tmp_tail + 1) % RCD_MAX_CNT)
		{
			//得到录波数据结构指针
			prcd = &g_rcd[tmp_tail];

			switch(prcd->state )
			{
			case RCD_ST_START_1:
				//初始化录波文件需要的辅助信息
				if(_rcd_init_wave(prcd)!=0)
				{
					rt_printf("录波初始化失败(sw=%lu,type=%lu)!\r\n", prcd->sw, prcd->type);
					prcd->state = RCD_ST_RECORD_ERR;
				}
				else
				{
					prcd->state = RCD_ST_RECORD;
				}
				break;
			case RCD_ST_RECORD:
				//录波未完成继续录波.如果录波已经完成，但是还没有写进文件，返回
				if(prcd->dt_cur != prcd->dt_end)
				{
					if(_rcd_save(prcd)<0)
					{
						rt_printf("录波失败(sw=%lu,type=%lu)!\r\n", prcd->sw, prcd->type);
						prcd->state = RCD_ST_RECORD_ERR;
					}
					 
				}
				else
				{	
					prcd->state = RCD_ST_RECORD_OK;

				}
				break;		
			}
		}
	}

	return 0;
}

#endif

void _rcd_file_cp(char *src, char *dst);
static int _rcd_write_buf_to_file(struct rcd *prcd)
{
	uint32_t us0;
	int ret = 0;
	u32 line,once;
	u32 dt_cur = prcd->dt_begin; 
	u32 dt_end = prcd->dt_end;
	u32 sw = prcd->sw;

	ret=_rcd_open_wave(prcd);
	if(ret !=0 )
	{
		rt_printf("创建录波文件失败\r\n");
		_rcd_close_wave(prcd);//应释放初始化的资源
		return -1;
	}

	rcd_write_cfg(prcd);

	//写dat文件
	us0 = ustimer_get_origin();
	
	prcd->pAn_no = 0;
	prcd->pDn_no = 0;
	line = (dt_end- dt_cur)*ADC_REC_SAMPLE_RATE;
	once = 0;
	while(line--)
	{
		prcd->f_dfs.n++;
		rcd_write_dat(prcd);
		
		if(++once == RCD_LINE_NUM)
		{
			once = 0;
			
			ret = sys_write(prcd->fd_dat, prcd->pdat_mem, prcd->pdat_mem_pos);
			if(ret!=prcd->pdat_mem_pos)
			{
				rt_printf("%s: sys_write(%d)=%d error\r\n", __func__, prcd->pdat_mem_pos, ret);	
			}
			prcd->pdat_mem_pos = 0;
		}
	}

	if(prcd->pdat_mem_pos)
	{
		ret = sys_write(prcd->fd_dat, prcd->pdat_mem, prcd->pdat_mem_pos);
		if(ret!=prcd->pdat_mem_pos)
		{
			rt_printf("%s: sys_write(%d)=%d error\r\n", __func__, prcd->pdat_mem_pos, ret);	
		}
		prcd->pdat_mem_pos = 0;
	}

	_rcd_close_wave(prcd);
	if(sw < SWITCH_NUM_MAX)
	{
		_rcd_save_to_flash(prcd);
	}

	if(prcd->type == RECORD_TYPE_SD)
	{
		rcd_sd_flag = 1;	//手动录波完成本标志	
	}
	
	rt_printf("录波%d周完成(sw=%d,type=%d)!\r\n",(prcd->dt_end - prcd->dt_begin)/CFG_ADC_DOTS_PER_PERIOD,sw,prcd->type);

	return 0;
}
int _rcd_writefile_thread(void * unused)
{
	int first_tail, tmp_tail;
	struct rcd *prcd;
	
	prctl(PR_SET_NAME, "_rcd_writefile_t");
	while(1)
	{
		msleep(50);
	#ifdef LINUX_KERNEL_APP		
		if(kthread_should_stop())
		{
			return 0;
		}
#else
		if(g_rcd_writefile_exit_flag)
		{
			return 0;
		}	
#endif

		//得到录波数据结构指针
		first_tail = rcd_tail;
		for(tmp_tail = rcd_tail; tmp_tail != rcd_head; tmp_tail = (tmp_tail + 1) % RCD_MAX_CNT)
		{
			//得到录波数据结构指针
			prcd = &g_rcd[tmp_tail];
			//如果录波完成，写录波数据到文件中
			if(prcd->state == RCD_ST_RECORD_OK)
			{
				//写录波数据到文件中
				_rcd_write_buf_to_file(prcd);
				//录波完成保存文件后，应当反初始化释放内存
				_rcd_uninit_wave(prcd);
				prcd->state = RCD_ST_FILE_OK;
			
			}

			if(prcd->state == RCD_ST_RECORD_ERR)
			{
				//录波失败，应当反初始化释放内存
				_rcd_uninit_wave(prcd);			
				prcd->state = RCD_ST_FILE_ERR;	
			}

			if((prcd->state == RCD_ST_FILE_OK) || (prcd->state == RCD_ST_FILE_ERR) )
			{
				if(first_tail == tmp_tail)
				{
					rcd_tail = (rcd_tail + 1) % RCD_MAX_CNT;
					first_tail = rcd_tail;	
					prcd->state =  RCD_ST_IDLE;
				}
			}
		}
	}
	
	return 0;
}

static int _rcd_get_sw_waveno(u32 sw, struct dir_file_ext_struct *pdfs, int filecnt, struct dir_file_ext_struct *pdfs_min)
{

	int i=0;
	char tmp[128];

	int rec_N=1; //序号

	struct dir_file_ext_struct   *p_max=0;
	struct dir_file_ext_struct   *p_min=0;
//	tar czvf P1.tar.gz BAY01_0001_20190822_142530_739.cfg BAY01_0001_20190822_142530_739.dat	两个文件压缩为一个文件
	sprintf(tmp, "BAY%02d", sw+1);

	//查找录波间隔序号为sw的最大序号的文件
	for(i=0; i<filecnt;i++)
	{
		if(strncmp(tmp, pdfs[i].file_name, 5)==0)
		{
			if(!p_max)
			{
				p_max = &pdfs[i];
				continue;
			}
			

			if(strncmp(pdfs[i].file_name, p_max->file_name, 10)>0)
			{
				p_max = &pdfs[i];	
			}
			
		}
	}
	
	//查找录波间隔序号为sw的最小序号的文件
	for(i=0; i<filecnt;i++)
	{
		if(strncmp(tmp, pdfs[i].file_name, 5)==0)
		{
			if(!p_min)
			{
				p_min = &pdfs[i];
				continue;
			}

			if(strncmp(pdfs[i].file_name, p_min->file_name, 10)<0)
			{
				p_min = &pdfs[i];	
			}
			
		}
	}
	

	if((!p_max) || (!p_min))  //没有找到
	{
		rec_N = 1;	
	}
	else if(p_max==p_min) //找到，但只有一个
	{
		if(p_min==pdfs_min) //该文件已经删除
		{
			rec_N = 1;	
		}
		else
		{
			 rec_N=simple_strtoul(p_min->file_name+6, NULL, 10);	
			 rec_N = (rec_N + 1) %(RCD_WAVE_MAX_NO+1);
			 if(rec_N==0) rec_N = 1;

		}
	} 
	else  //有多个
	{
		int rec_N1=0;
		int rec_N2=0;
		int rec_N3=0;

		 rec_N1=simple_strtoul(p_min->file_name+6, NULL, 10);	
		 rec_N2=simple_strtoul(p_max->file_name+6, NULL, 10);	

		if((rec_N1+RCD_MAX_FILES) >= rec_N2) //两者之差.如果两者之差大于RCD_MAX_FILES，则说明应该递加最大序号
		{
			 rec_N = (rec_N2 + 1) %(RCD_WAVE_MAX_NO+1);
			 if(rec_N==0) rec_N = 1;			
		}
		else  //存在回绕，小心处理
		{

		
			//查找录波间隔序号为sw的最新序号的文件
			for(i=0; i<filecnt;i++)
			{
				if(strncmp(tmp, pdfs[i].file_name, 5)==0)
				{

					 rec_N1=simple_strtoul(pdfs[i].file_name+6, NULL, 10);	
					//等于
					 if((rec_N1+RCD_MAX_FILES) < rec_N2)
					 {
					 	rec_N3 = rec_N1;
						
					 	continue;
					 }
					 else
					 {
						break;
					 }
					
				}
			}
			
			 rec_N = (rec_N3+ 1) %(RCD_WAVE_MAX_NO+1);
			 if(rec_N==0) rec_N = 1;		
		}
		
		
	}

	 
	//sprintf(tmp, "%sBAY%02d_%04d_%s", RCD_FILE_PATH,  sw, rec_N,   g_rcd[sw].tmp_cfg+16); 

	//rt_file_mv(g_rcd[sw].tmp_cfg, tmp);
	
	//sprintf(tmp, "%sBAY%02d_%04d_%s", RCD_FILE_PATH,  sw, rec_N,   g_rcd[sw].tmp_dat+16); 

	//rt_file_mv(g_rcd[sw].tmp_dat, tmp);		
			
	return rec_N;		

}

//获取对应的故障录波序号
void _rcd_get_waveno(void)
{

	struct dir_file_ext_struct *pdfs;
	struct dir_file_ext_struct *pdfs_min=0;
	int file_cnt = 0;
	char tmp[128];
//	char addr[]={0,0,0,0,0};
	int i=0;
	


	sprintf(tmp, "/tmp/sw%d", 0);

	pdfs = hf_get_dir_file_ext(RCD_FILE_PATH, &file_cnt, tmp);
	
	
	if(file_cnt >= (RCD_MAX_FILES*2))
	{

		//找到最早的文件，并删除
		pdfs_min = pdfs;
		for(i=1;i<file_cnt;i++)
		{
			if(strncmp(pdfs[i].file_name+11, pdfs_min->file_name+11, 19) < 0)
			{
				pdfs_min	= &pdfs[i];
			}
		}

		
	}

#ifdef	RCD_STRAN_S	
	for(i=0;i<SWITCH_NUM_MAX;i++)
	{		
		g_new_waveno[i] = _rcd_get_sw_waveno(tRunPara.byAddr-1, pdfs, file_cnt, pdfs_min);	
	}
#else
	for(i=0;i<SWITCH_NUM_MAX;i++)
	{
		g_new_waveno[i] = _rcd_get_sw_waveno(i, pdfs, file_cnt, pdfs_min);
	}
#endif


	if(pdfs)
	{
		rt_free(pdfs);
	}

	
}


static void _rcd_save_to_flash(struct rcd *prcd)
{

	struct dir_file_ext_struct *pdfs;
	struct dir_file_ext_struct *pdfs_min=0;
	int file_cnt = 0;
	char tmp[128];
	int i=0,ret;
	u32 sw =prcd->sw;
//	u32 type = prcd->type;
	
	struct dir_file_ext_struct *pdfs2=0;
	int file_cnt2 = 0;
	char tmp2[128];
	
	if(pRunSet->bTT_LogPrintf)
	{
		sprintf(tmp2, "/tmp/_sw%02d%u", sw, prcd->dt_begin);
		pdfs2 = hf_get_dir_file_ext(RCD_BACKUP_PATH, &file_cnt2, tmp2);
		if(pdfs2)
		{
			rt_free(pdfs2);
		}		
	}
	
	sprintf(tmp, "/tmp/sw%02d%u", sw, prcd->dt_begin);

	pdfs = hf_get_dir_file_ext(RCD_FILE_PATH, &file_cnt, tmp);


	//备份区文件未满
	if(pRunSet->bTT_LogPrintf && (file_cnt2 < (RCD_BACKUP_MAX_FILES*2)))
	{
		sprintf(tmp, "%s%s", RCD_BACKUP_PATH,  prcd->tmp_cfg+5); 
		ret = rt_file_mv(prcd->tmp_cfg, tmp);
		if(ret != 0)
		{
			rt_printf("%s 文件移动失败(ret=%d)!\r\n",prcd->tmp_cfg,ret);
			rt_file_del(prcd->tmp_cfg);
		}	

		sprintf(tmp, "%s%s", RCD_BACKUP_PATH,  prcd->tmp_dat+5); 
		
		ret = rt_file_mv(prcd->tmp_dat, tmp);
		if(ret != 0)
		{
			rt_printf("%s 文件移动失败(ret=%d)!\r\n",prcd->tmp_dat,ret);
			rt_file_del(prcd->tmp_dat);
		}
		
		sprintf(tmp, "%s%s", RCD_BACKUP_PATH,  prcd->tmp_cfg+5); 
		sprintf(tmp2, "%s%s", RCD_FILE_PATH,  prcd->tmp_cfg+5); 
		
		//创建软链接
		ret=rt_file_ln(tmp, tmp2);
		if(ret != 0)
		{
			rt_printf("%s 文件链接失败(ret=%d)!\r\n",prcd->tmp_cfg,ret);
		}	
	#ifdef	RCD_STRAN_S
		iec_commadd_rcd(prcd->tmp_cfg+5);	
	#endif
		
		sprintf(tmp, "%s%s",  RCD_BACKUP_PATH,  prcd->tmp_dat+5); 
		sprintf(tmp2, "%s%s",  RCD_FILE_PATH,  prcd->tmp_dat+5); 
		//创建软链接
		ret=rt_file_ln(tmp, tmp2);
		if(ret != 0)
		{
			rt_printf("%s 文件链接失败(ret=%d)!\r\n",prcd->tmp_dat,ret);
		}	
	#ifdef	RCD_STRAN_S
		iec_commadd_rcd(prcd->tmp_dat+5);	
	#endif

	}
	else //备份文件区满
	{

		sprintf(tmp, "%s%s", RCD_FILE_PATH,  prcd->tmp_cfg+5); 
		//rt_printf("%s,%s\r\n", tmp ,prcd->tmp_cfg+5);
		
		ret = rt_file_mv(prcd->tmp_cfg, tmp);
		if(ret != 0)
		{
			rt_printf("%s 文件移动失败(ret=%d)!\r\n",prcd->tmp_cfg,ret);
			rt_file_del(prcd->tmp_cfg);
		}
	#ifdef	RCD_STRAN_S
		iec_commadd_rcd(prcd->tmp_cfg+5);	
	#endif
		
		sprintf(tmp, "%s%s",  RCD_FILE_PATH,  prcd->tmp_dat+5); 
		//rt_printf("%s,%s\r\n", tmp ,prcd->tmp_dat+5);
		ret = rt_file_mv(prcd->tmp_dat, tmp);	
		if(ret != 0)
		{
			rt_printf("%s 文件移动失败(ret=%d)!\r\n",prcd->tmp_dat,ret);
			rt_file_del(prcd->tmp_dat);
		}
	#ifdef	RCD_STRAN_S
		iec_commadd_rcd(prcd->tmp_dat+5);	
	#endif
	}
		
	if((file_cnt+2) > (RCD_MAX_FILES*2))
	{
		//找到最早的文件，并删除
		pdfs_min = pdfs;
		for(i=1;i<file_cnt;i++)
		{
			if(strncmp(pdfs[i].file_name+11, pdfs_min->file_name+11, 19) < 0)
			{
				pdfs_min	= &pdfs[i];
			}
		}	

		//因为文件以及已经排好序，找到第一个是cfg文件，第二个是dat文件
		//先删除.cfg文件
		sprintf(tmp, "%s%s", RCD_FILE_PATH,pdfs_min->file_name);	
		rt_file_del(tmp);
		
		sprintf(tmp, "%s%s", RCD_FILE_PATH,pdfs_min[1].file_name);	
		rt_file_del(tmp);
	}
	
	if(pdfs)
	{
		rt_free(pdfs);
	}
}


void _rcd_file_cp(char *src, char *dst)
{
	int fd_src;
	int fd_dst;
	char *p_src;
	struct stat s;	
	int ret;
	

	if(sys_newstat(src, &s))
	{		rt_printf("%s:sys_newstat(%s) error\n",__func__, src);
		return ;
	}

	p_src = rt_malloc(s.st_size);
	if(!p_src)
	{
		return;
	}
	
	fd_src = sys_open(src, O_RDONLY, 0);
	
	if(fd_src <=0)
	{
		rt_printf("%s:sys_open(%s) error\n",__func__, src);
		rt_free(p_src);
		return;
	}	
	
	ret = sys_read(fd_src, p_src, s.st_size);
	if(ret != s.st_size)
	{
		rt_free(p_src);
		sys_close(fd_src);
		rt_printf("%s:sys_read(%s) error\n",__func__, src);
		return;
	}
		
	sys_close(fd_src);
	

	

	fd_dst = sys_open(dst, O_CREAT|O_RDWR|O_TRUNC , 0777);
	if(fd_dst <=0)
	{
		rt_free(p_src);
		rt_printf("%s:sys_open(%s) error\n",__func__, dst);
		return;
	}	

	ret = sys_write(fd_dst, p_src, s.st_size);
	if(ret!=s.st_size)
	{
		rt_printf("%s:sys_write(%s) error\n",__func__, dst);
		rt_free(p_src);
		sys_close(fd_dst);
		return;		
	}

	rt_free(p_src);
	sys_close(fd_dst);
	

}



int rcd_write_cfg(struct rcd *prcd)
{

	int ret;
	int len;
	int i;
	char comma[]={',', 0};
	char cr_line[]={'\r',  '\n', 0};
//	char tmp[128];
	char *buf;
	int  f_handle;
	struct cfg_file_struct  *p_cfg;
//	u32 sw=prcd->sw;
//	u32 type=prcd->type;

	//没有分配内存，返回
	if(!prcd->pcfg_mem)
	{
		return -1;
	}

	//内存使用完毕，返回
	if(prcd->pcfg_mem_pos > prcd->pcfg_mem_size)
	{
		return -1;
	}


	f_handle = prcd->fd_cfg;
	p_cfg = &prcd->f_cfs;
	
	// 	站名、录波装置编号、版本年代
	// 站名

	len=strlen(p_cfg->srr.station_name);

	memcpy(prcd->pcfg_mem+prcd->pcfg_mem_pos, p_cfg->srr.station_name, len);
	prcd->pcfg_mem_pos += (u32)len;	

	

	memcpy(prcd->pcfg_mem+prcd->pcfg_mem_pos, comma, 1);
	prcd->pcfg_mem_pos +=1;

	//录波装置编号
	len=strlen(p_cfg->srr.rec_dev_id);
	

	memcpy(prcd->pcfg_mem+prcd->pcfg_mem_pos, p_cfg->srr.rec_dev_id, len);
	prcd->pcfg_mem_pos +=(u32)len;

	memcpy(prcd->pcfg_mem+prcd->pcfg_mem_pos, comma, 1);
	prcd->pcfg_mem_pos +=1;

	//版本年代
	len=strlen(p_cfg->srr.rev_year);



	memcpy(prcd->pcfg_mem+prcd->pcfg_mem_pos, p_cfg->srr.rev_year, len);
	prcd->pcfg_mem_pos +=(u32)len;

	memcpy(prcd->pcfg_mem+prcd->pcfg_mem_pos, cr_line, 2);
	prcd->pcfg_mem_pos +=2;

	buf = prcd->pcfg_mem+prcd->pcfg_mem_pos;	
	// 	通道的种类和数量


	//通道总数
	buf += sprintf(buf, "%d,%dA,%dD\r\n", p_cfg->tt.A+p_cfg->tt.D,  p_cfg->tt.A,  p_cfg->tt.D);
	
	// 	模拟通道信息
	for(i=0;i<p_cfg->tt.A;i++)
	{
		//通道的索引, 通道标识符	
		buf +=sprintf(buf, "%d,%s,", p_cfg->tt_a[i].An, p_cfg->tt_a[i].ch_id);	


		//通道相位标识符,被检测的电路组件, 通道的单位
		buf +=sprintf(buf, "%s,%s,%s,", p_cfg->tt_a[i].Ph, p_cfg->tt_a[i].Ccb, p_cfg->tt_a[i].Uu);	
	

		//通道点值的倍数, 通道值偏移量
		buf +=sprintf(buf, "%f,%f,", p_cfg->tt_a[i].a, p_cfg->tt_a[i].b);		
		
		//通道从采样开始的时间偏移,此通道中的最小值,此通道中的最大值
		buf +=sprintf(buf, "%f,%d,%d,", p_cfg->tt_a[i].skew, p_cfg->tt_a[i].min, p_cfg->tt_a[i].max);	

		
		//通道电压或电流变压器一次线圈比例系数,通道电压或电流变压器二次线圈比例系数,采用primary 值还是secondary值
		buf +=sprintf(buf, "%f,%f,%s\r\n", p_cfg->tt_a[i].primary, p_cfg->tt_a[i].secondary,  p_cfg->tt_a[i].ps);			


		
	}
	

	// 	开关量（数字）通道信息
	for(i=0;i<p_cfg->tt.D;i++)
	{
		//status通道索引,通道名称
		buf +=sprintf(buf, "%d,%s,", p_cfg->tt_d[i].Dn, p_cfg->tt_d[i].ch_id);			

		//通道的相位标识符	,被检测的电路组件,开关量通道的状态
		buf +=sprintf(buf,  "%s,%s,%d\r\n", p_cfg->tt_d[i].ph, p_cfg->tt_d[i].ccbm, p_cfg->tt_d[i].Y);		

		
	}


	// 	线路频率	
	buf +=sprintf(buf, "%f\r\n", p_cfg->Lf);	
	

	// 	采样速率信息
	
	buf +=sprintf(buf,  "%d\r\n%f,%d\r\n", p_cfg->si.nrates, p_cfg->si.samp, p_cfg->si.endsamp);


	// 	时间/日期信息
	
	buf +=sprintf(buf, "%s\r\n%s\r\n", p_cfg->date_i.firsttime, p_cfg->date_i.trigger_point_ime);

	
	//文件格式信息

	buf +=sprintf(buf, "%s\r\n", p_cfg->ft);



	// 	时间倍乘因数
	buf +=sprintf(buf,  "%s\r\n", p_cfg->timemult);


	prcd->pcfg_mem_pos += buf - (prcd->pcfg_mem+prcd->pcfg_mem_pos);
	ret = sys_write(prcd->fd_cfg, prcd->pcfg_mem, prcd->pcfg_mem_pos );
	if(ret!=prcd->pcfg_mem_pos)
	{
		rt_printf("%s: sys_write(%d)=%d error\r\n", __func__, prcd->pcfg_mem_pos, ret);	
	}

	prcd->pcfg_mem_pos = 0;

	return 0;
}

static int  rcd_write_dat_ascii(struct rcd *prcd)
{

	int i;
	char *buf;
	struct  dat_file_struct *p_dat;
//	u32 sw=prcd->sw;
//	u32 type=prcd->type;
	p_dat = &prcd->f_dfs;
	buf = prcd->pdat_mem + prcd->pdat_mem_pos;
	
	//采样编号,采样时间
	buf += sprintf(buf, "%d,%u,", p_dat->n, p_dat->timestamp);
	p_dat->timestamp +=  prcd->samp_t;

	//模拟通道的数据
	for(i=0;i<prcd->f_cfs.tt_a_cnt;i++)
	{
		buf += sprintf(buf, "%d,", prcd->pAn[prcd->pAn_no++]);
	}

	//开关量通道数据
	for(i=0;i<prcd->f_cfs.tt_d_cnt;i++)
	{
		buf += sprintf(buf, "%d,", prcd->pDn[prcd->pDn_no++]);	
	}	

	// 删除最后的逗号
	buf--;

	// 回车换行符
	buf += sprintf(buf, "\r\n");	

	// 修正pdat_mem_pos
	prcd->pdat_mem_pos = buf - prcd->pdat_mem;
	
	return 0;

}

static int   rcd_write_dat_binary(struct rcd *prcd)
{

	int i;
	char *buf;
	struct  dat_file_struct *p_dat;
//	u32 sw = prcd->sw;
//	u32 type = prcd->type;

	p_dat = &prcd->f_dfs;
	buf = prcd->pdat_mem + prcd->pdat_mem_pos;
	
	//采样编号,采样时间
	*buf++ = (p_dat->n >> 0) & 0xFF;
	*buf++ = (p_dat->n >> 8) & 0xFF;
	*buf++ = (p_dat->n >> 16) & 0xFF;
	*buf++ = (p_dat->n >> 24) & 0xFF;
	
	
	
	*buf++ = (p_dat->timestamp >> 0) & 0xFF;	
	*buf++ = (p_dat->timestamp >> 8) & 0xFF;
	*buf++ = (p_dat->timestamp >> 16) & 0xFF;
	*buf++ = (p_dat->timestamp >> 24) & 0xFF;
	
	
	
	
	//buf += sprintf(buf, "%d,%u,", p_dat->n, p_dat->timestamp);
	p_dat->timestamp +=  prcd->samp_t;

	//模拟通道的数据
	for(i=0;i<prcd->f_cfs.tt_a_cnt;i++)
	{
		//buf += sprintf(buf, "%d,", g_rcd[sw].pAn[g_rcd[sw].pAn_no++]);
		*buf++ =  (prcd->pAn[prcd->pAn_no] >>  0) & 0xFF;
		*buf++ =  (prcd->pAn[prcd->pAn_no] >>  8) & 0xFF;
		prcd->pAn_no++;
		
	}

	//开关量通道数据
	if(prcd->f_cfs.tt_d_cnt)
	{
		u16 d=0;
		int j=0;
		
		for(i=0;i<prcd->f_cfs.tt_d_cnt;i++)
		{
		
			d |= (prcd->pDn[prcd->pDn_no++] << (i-j*16)) & 0xFFFF;	
			
			if(i%16==15)
			{
				*buf++=(u8)(d & 0xFF);
				*buf++=(u8)((d >> 8) & 0xFF);
				j++;
				d = 0;
			}				
			
		}	 

		if(i%16 != 0)
		{
			*buf++=(u8)(d & 0xFF);
			*buf++=(u8)((d >> 8) & 0xFF);			
		}
		
	}

	// 删除最后的逗号
	//buf--;

	// 回车换行符
	//buf += sprintf(buf, "\r\n");	

	// 修正pdat_mem_pos
	prcd->pdat_mem_pos = buf - prcd->pdat_mem;
	
	return 0;

}

int   rcd_write_dat(struct rcd *prcd)
{
	int ret = 0;
	if(g_wave_filetype==0)
	{
		ret = rcd_write_dat_ascii(prcd);
	}
	else
	{
		ret = rcd_write_dat_binary(prcd);	
	}
	return ret;
}

int rcd_get_A_D_N(char *data, int *pA, int *pD, int *pN, int *pUI)  //获取模拟通道数，状态通道数,采样数
{
	char *p;
	char *p1;
	char *p2;
	int A;
	int D;
	char comma[]={',', 0}; 
	char star[]={'*', 0}; 
	char question[]={'?', 0}; 
	char line[]={'\n', 0}; 
	int cnt = 0;
	int i=0;
	static char tmpbuf[256];

	p=data;

	while(p)
	{
		p=strstr(p, line);
		if(!p)
		{
			break;
		}
		p = p + 2;
		cnt++;
	}

	if(cnt < 9)
	{
		rt_printf("不合法的文件格式!\r\n");
		return -1;
	}

	p=data;
	p=strstr(p, line);
	p=p+2;

	p1 = strstr(p, comma);

	if(!p1)
	{
		rt_printf("没有找到通道总数!\r\n");
		return -1;
	}

	p1++;
	A=simple_strtoul(p1, NULL, 10);
	if(A==0)   //注意，模拟通道数不能为0
	{
		rt_printf("没有找到模拟通道数!\r\n");
		return -1;	
	}

	*pA = A;	


	p1 = strstr(p1, comma);
	if(!p1)
	{
		rt_printf("没有找到状态数!\r\n");
		return -1;
	}
	p1++;	
	D=simple_strtoul(p1, NULL, 10);
	*pD = D;

	p1=strstr(p1, line);


	p1=p1+2;
	
	for(i=0;i<A;i++)
	{
		memset(tmpbuf, 0, sizeof(tmpbuf));
		p2 = p1;

		p1=strstr(p1 ,line);

		memcpy(tmpbuf, p2, p1-p2);
		p1 = strstr(tmpbuf, "U0");
		if(p1 == NULL)
		{
			p1 = strstr(tmpbuf, "UZ");
		}
		
		if(p1)
		{
			pUI[i] = 0; //零序电压
		}
		else
		{
			p1 = strstr(tmpbuf, "I0");
			if(p1 == NULL)
			{
				p1 = strstr(tmpbuf, "IZ");
			}
			if(p1)
			{
				p1 = strstr(tmpbuf, star);
				pUI[i] = p1 ? 2:1;	//零序电流,2为故障线路
				p1 = strstr(tmpbuf, question);
				if(p1)
				{
					pUI[i] += 10;			//零序电流,大于10为问题线路
				}
			}
			else
			{
				pUI[i] = -1;//不是零序电压或电流
				
			}
	

		}

		p1=p2;
		
		
		p1=strstr(p1, line);
		if(!p1)
		{
			return -1;
		}
		p1=p1+2;
		
	}

	for(i=0;i<(D+2);i++)
	{
		p1=strstr(p1, line);
		if(!p1)
		{
			return -1;
		}
		p1=p1+2;		
	}
	
	p1=strstr(p1, comma);
	if(!p1)
	{
		rt_printf("没有找到采样数!\r\n");
		return -1;
	}

	p1++;
	
	*pN = simple_strtoul(p1, NULL, 10);
	 
	return 0;
}

#if 0
void testwavefile(void)
{
	int f_handle;
	static struct cfg_file_struct  cfs;
	static struct dat_file_struct dfs[3];
	

	memset(&cfs, 0, sizeof(cfs));
	memset(&dfs, 0, sizeof(dfs)*3);
	
	memcpy(cfs.srr.station_name, "变电站名称", 10);
	memcpy(cfs.srr.rec_dev_id,"0", 1);
	memcpy(cfs.srr.rev_year,"1999", 4);


	cfs.tt.A=8;
	cfs.tt.D=2;

	cfs.tt_a = rt_malloc(cfs.tt.A*sizeof(struct cfg_file_TT_A));
	if(!cfs.tt_a)
	{
		printk("rt_malloc error\r\n");
		return;
	}

	memset(cfs.tt_a, 0, cfs.tt.A*sizeof(struct cfg_file_TT_A));

	cfs.tt_a[0].An=1;
	memcpy(cfs.tt_a[0].ch_id, "母线A相电压", strlen("母线A相电压"));


	memcpy(cfs.tt_a[0].Ph, "A", 1);
	memcpy(cfs.tt_a[0].Uu, "V", 1);
	cfs.tt_a[0].a = 0.010011;
	cfs.tt_a[0].b = 0.000000;
	cfs.tt_a[0].skew = 0.000000;
	cfs.tt_a[0].min = -32767;
	cfs.tt_a[0].max= 32767;
	cfs.tt_a[0].primary=1100.000000; 
	cfs.tt_a[0].secondary=1.000000; 
	memcpy(cfs.tt_a[0].ps, "S", 1);



	cfs.tt_a[1].An=2;
	memcpy(cfs.tt_a[1].ch_id, "母线B相电压", strlen("母线B相电压"));
	memcpy(cfs.tt_a[1].Ph, "B", 1);
	memcpy(cfs.tt_a[1].Uu, "V", 1);
	cfs.tt_a[1].a = 0.010011;
	cfs.tt_a[1].b = 0.000000;
	cfs.tt_a[1].skew = 0.000000;
	cfs.tt_a[1].min = -32767;
	cfs.tt_a[1].max= 32767;
	cfs.tt_a[1].primary=1100.000000; 
	cfs.tt_a[1].secondary=1.000000; 
	memcpy(cfs.tt_a[1].ps, "S", 1);

	cfs.tt_a[2].An=3;
	memcpy(cfs.tt_a[2].ch_id, "母线C相电压", 11);
	memcpy(cfs.tt_a[2].Ph, "C", 1);
	memcpy(cfs.tt_a[2].Uu, "V", 1);
	cfs.tt_a[2].a = 0.010011;
	cfs.tt_a[2].b = 0.000000;
	cfs.tt_a[2].skew = 0.000000;
	cfs.tt_a[2].min = -32767;
	cfs.tt_a[2].max= 32767;
	cfs.tt_a[2].primary=1100.000000; 
	cfs.tt_a[2].secondary=1.000000; 
	memcpy(cfs.tt_a[2].ps, "S", 1);
	


	cfs.tt_a[3].An=4;
	memcpy(cfs.tt_a[3].ch_id, "母线A相电流", 11);
	memcpy(cfs.tt_a[3].Ph, "A", 1);
	memcpy(cfs.tt_a[3].Uu, "A", 1);
	cfs.tt_a[3].a = 0.010011;
	cfs.tt_a[3].b = 0.000000;
	cfs.tt_a[3].skew = 0.000000;
	cfs.tt_a[3].min = -32767;
	cfs.tt_a[3].max= 32767;
	cfs.tt_a[3].primary=1100.000000; 
	cfs.tt_a[3].secondary=1.000000; 
	memcpy(cfs.tt_a[3].ps, "S", 1);



	cfs.tt_a[4].An=5;
	memcpy(cfs.tt_a[4].ch_id, "母线B相电流", 11);
	memcpy(cfs.tt_a[4].Ph, "B", 1);
	memcpy(cfs.tt_a[4].Uu, "A", 1);
	cfs.tt_a[4].a = 0.010011;
	cfs.tt_a[4].b = 0.000000;
	cfs.tt_a[4].skew = 0.000000;
	cfs.tt_a[4].min = -32767;
	cfs.tt_a[4].max= 32767;
	cfs.tt_a[4].primary=1100.000000; 
	cfs.tt_a[4].secondary=1.000000; 
	memcpy(cfs.tt_a[4].ps, "S", 1);


	cfs.tt_a[5].An=6;
	memcpy(cfs.tt_a[5].ch_id, "母线C相电流", 11);
	memcpy(cfs.tt_a[5].Ph, "C", 1);
	memcpy(cfs.tt_a[5].Uu, "A", 1);
	cfs.tt_a[5].a = 0.010011;
	cfs.tt_a[5].b = 0.000000;
	cfs.tt_a[5].skew = 0.000000;
	cfs.tt_a[5].min = -32767;
	cfs.tt_a[5].max= 32767;
	cfs.tt_a[5].primary=1100.000000; 
	cfs.tt_a[5].secondary=1.000000; 
	memcpy(cfs.tt_a[5].ps, "S", 1);



	cfs.tt_a[6].An=7;
	memcpy(cfs.tt_a[6].ch_id, "线路零序电流", 12);
	//memcpy(cfs.tt_a[6].Ph, "C", 1);
	memcpy(cfs.tt_a[6].Uu, "A", 1);
	cfs.tt_a[6].a = 0.010011;
	cfs.tt_a[6].b = 0.000000;
	cfs.tt_a[6].skew = 0.000000;
	cfs.tt_a[6].min = -32767;
	cfs.tt_a[6].max= 32767;
	cfs.tt_a[6].primary=1100.000000; 
	cfs.tt_a[6].secondary=1.000000; 
	memcpy(cfs.tt_a[6].ps, "S", 1);
	
	cfs.tt_a[7].An=8;
	memcpy(cfs.tt_a[7].ch_id, "线路侧电压", 10);
	//memcpy(cfs.tt_a[6].Ph, "C", 1);
	memcpy(cfs.tt_a[7].Uu, "V", 1);
	cfs.tt_a[7].a = 0.010011;
	cfs.tt_a[7].b = 0.000000;
	cfs.tt_a[7].skew = 0.000000;
	cfs.tt_a[7].min = -32767;
	cfs.tt_a[7].max= 32767;
	cfs.tt_a[7].primary=1100.000000; 
	cfs.tt_a[7].secondary=1.000000; 
	memcpy(cfs.tt_a[7].ps, "S", 1);
	
	cfs.tt_d = rt_malloc(cfs.tt.D*sizeof(struct cfg_file_TT_D));
	if(!cfs.tt_a)
	{
		printk("rt_malloc error\r\n");
		rt_free(cfs.tt_a );
		return;
	}
	memset(cfs.tt_d, 0, cfs.tt.D*sizeof(struct cfg_file_TT_D));

	cfs.tt_d[0].Dn = 1;
	memcpy(cfs.tt_d[0].ch_id, "开关合位", 8);
	cfs.tt_d[0].Y=0;	

	cfs.tt_d[1].Dn = 2;
	memcpy(cfs.tt_d[1].ch_id, "开关分位", 8);
	cfs.tt_d[1].Y=0;	



	cfs.Lf = 50;

	
	cfs.si.nrates=1;
	cfs.si.samp=1200;
	cfs.si.endsamp=64;

	memcpy(cfs.date_i.firsttime, "14/11/2014,19:21:35.810024", 26);
	memcpy(cfs.date_i.trigger_point_ime, "14/11/2014,19:21:35.830000", 26);
	memcpy(cfs.ft, "ASCII", 5);
	memcpy(cfs.timemult, "1", 1);
	

	f_handle=sys_open("/tmp/testwave.cfg",O_CREAT|O_RDWR | O_TRUNC|O_SYNC, 0777);
	if( f_handle < 0)
	{
		return;
	}


	rcd_write_cfg(f_handle, &cfs);
	
	rt_free(cfs.tt_d) ;
	rt_free(cfs.tt_a); 
	sys_close(f_handle);


	dfs[0].n=1;
	dfs[0].timestamp=0;
	dfs[0].An[0]=7294;
	dfs[0].An[1]=-447;
	dfs[0].An[2]=-6797;
	dfs[0].An[3]=-2;
	dfs[0].An[4]=14;
	dfs[0].An[5]=7;
	dfs[0].An[6]=19;
	dfs[0].An[7]=0;
	dfs[0].Dn[0]=0;
	dfs[0].Dn[1]=0;


	dfs[1].n=2;
	dfs[1].timestamp=833;
	dfs[1].An[0]=6089;
	dfs[1].An[1]=1658;
	dfs[1].An[2]=-7715;
	dfs[1].An[3]=-11;
	dfs[1].An[4]=12;
	dfs[1].An[5]=-1;
	dfs[1].An[6]=-1;
	dfs[1].An[7]=0;
	dfs[1].Dn[0]=0;
	dfs[1].Dn[1]=0;


	dfs[2].n=3;
	dfs[2].timestamp=1666;
	dfs[2].An[0]=4495;
	dfs[2].An[1]=3649;
	dfs[2].An[2]=-8122;
	dfs[2].An[3]=-2;
	dfs[2].An[4]=26;
	dfs[2].An[5]=2;
	dfs[2].An[6]=26;
	dfs[2].An[7]=0;
	dfs[2].Dn[0]=0;
	dfs[2].Dn[1]=0;	

	f_handle=sys_open("/tmp/testwave.dat",O_CREAT|O_RDWR | O_TRUNC|O_SYNC, 0777);
	if(f_handle < 0)
	{
		return;
	}	

	rcd_write_dat(0);
	rcd_write_dat(1);
	rcd_write_dat(2);

	sys_close(f_handle);


}
#endif

/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/



