/****************************************************************************** 版权所有: 文件名称: record.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2013-06-20 功能说明: 录波处理。 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" #ifdef LINUX_KERNEL_APP #include #include #else #include #include #include #include #include #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;if_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;if_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;if_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;iac_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; if_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]; #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<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;if_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< %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; if_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; isw; // 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;loopdt_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; ifile_name, 10)>0) { p_max = &pdfs[i]; } } } //查找录波间隔序号为sw的最小序号的文件 for(i=0; ifile_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= (RCD_MAX_FILES*2)) { //找到最早的文件,并删除 pdfs_min = pdfs; for(i=1;ifile_name+11, 19) < 0) { pdfs_min = &pdfs[i]; } } } #ifdef RCD_STRAN_S for(i=0;isw; // 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;ifile_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;itt.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;itt.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;if_cfs.tt_a_cnt;i++) { buf += sprintf(buf, "%d,", prcd->pAn[prcd->pAn_no++]); } //开关量通道数据 for(i=0;if_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;if_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;if_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