/******************************************************************************
版权所有：	
文件名称：	iectable.c
文件版本：	01.01
创建作者：	xxxxxx
创建日期：	2013-05-29
功能说明：	DTU点表处理程序
其它说明：
	逻辑点：Logic Point(缩写 lp )，代表DFTU逻辑模型中的各种点资源，和具体通道配置无关。
	通讯点：Communication Point(缩写 cp )，和后台通讯的三遥地址编号，从转发点表中取出。
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include "head.h"
#ifdef LINUX_KERNEL_APP
#include <linux/delay.h> 
#endif

/*------------------------------- 宏定义 --------------------------------------
*/
#ifdef IECTABLE_NEWDPI_V106
#define RSC_FILE_VERSION	0X01010106	//资源表文件版本 配合维护工具增加遥信单双点的单独配置
#else
#define RSC_FILE_VERSION	0X01010105	//资源表文件版本
#endif

/*------------------------------ 全局变量 -------------------------------------
*/
struct rsc_file_head_data	*g_rsc_head;
struct di_rsc		*g_di_pub_rsc;
struct do_rsc		*g_do_pub_rsc;
struct ac_rsc		*g_ac_pub_rsc;

struct di_rsc		*g_di_sw_rsc;
struct do_rsc		*g_do_sw_rsc;
struct ac_rsc		*g_ac_sw_rsc;

struct led_rsc		*g_led_rsc;

struct unit_rsc		*g_unit_rsc;

// 转发点表文件
struct table_file_head_data	g_table_head_null;					// 全0结构，防止访问异常
struct table_file_head_data	*g_table_head = &g_table_head_null;	// 转发点表文件头
struct di_table				*g_di_table;
struct di_merge_table 		*g_di_merge_table;
struct di_db_table			*g_di_db_table;
#ifdef FUN_DIMER_LINK
struct di_table				*g_di_info_merge_table;
u32 g_di_info_merge_num; //个数
#endif
struct do_table				*g_do_table;
struct ac_table				*g_ac_table;
struct sz_table				*g_sz_table;
struct dd_table				*g_dd_table;

struct file_contrast		rsc_contrast;

u16 g_crc_rsc;
u16 g_crc_rectable;

// 转发点表相关遥控信息
REMOTEYKSTATUS *g_yk_info;

// 级联点表
u32 g_lt_di_num = 0;
u32 g_lt_do_num = 0;
u32 g_lt_ac_num = 0;
u32 g_lt_dd_num = 0;
LINK_TABLE *g_lt_di = NULL;
LINK_TABLE *g_lt_do = NULL;
LINK_TABLE *g_lt_ac = NULL;
LINK_TABLE *g_lt_dd = NULL;


/*------------------------------ 函数声明 -------------------------------------
*/


/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/
/**************************************************************************
函数名称：create_rsc_file
函数版本：1.00 
作者：   
创建日期：2013.05.30     
函数功能说明：生成资源表文件
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
int tbl_create_rsc(void)
{
	unsigned int i,j,file_length;
	char *p;
	loff_t pos;
	
	struct file * pfile;
	struct rsc_file_head_data	fh;
	struct di_rsc disrc;
	struct do_rsc dosrc;
	struct ac_rsc acsrc;
	struct unit_rsc unitsrc;
	struct led_rsc ledsrc;
	struct dd_rsc ddsrc;

	// 写文件头
	// 配置文件头
	memset(&fh,0,sizeof(fh));
	fh.cfh.signature = SIG_RSC_FILE;
	fh.cfh.version = RSC_FILE_VERSION;

	//装置类型

	// 公共类三遥资源
	fh.pub_di_addr = FILE_ADDR_ALGIN(sizeof(fh));
	fh.pub_di_num = PUB_DI_NUM+EV_PUB_END-EV_PUB_START;

	fh.pub_do_addr = FILE_ADDR_ALGIN(fh.pub_di_addr + fh.pub_di_num * sizeof(struct di_rsc));
	fh.pub_do_num = PUB_DO_NUM;

	fh.pub_ac_addr = FILE_ADDR_ALGIN(fh.pub_do_addr + fh.pub_do_num * sizeof(struct do_rsc));
	fh.pub_ac_num = PUB_AC_NUM_ALL;

	// 开关类三遥资源
	fh.sw_di_addr = FILE_ADDR_ALGIN(fh.pub_ac_addr + fh.pub_ac_num * sizeof(struct ac_rsc));
	fh.sw_di_num = SW_DI_NUM+EV_SW_NUM;

	fh.sw_do_addr = FILE_ADDR_ALGIN(fh.sw_di_addr + fh.sw_di_num * sizeof(struct di_rsc));
	fh.sw_do_num = SW_DO_NUM;

	fh.sw_ac_addr = FILE_ADDR_ALGIN(fh.sw_do_addr + fh.sw_do_num * sizeof(struct do_rsc));
	fh.sw_ac_num = SW_AC_NUM_ALL;

	// 单位表
	fh.unit_addr = FILE_ADDR_ALGIN(fh.sw_ac_addr + fh.sw_ac_num * sizeof(struct ac_rsc));
	fh.unit_num = UNIT_NUM;

	// LED资源
	fh.led_addr = FILE_ADDR_ALGIN(fh.unit_addr + fh.unit_num * sizeof(struct unit_rsc));
	fh.led_num = SW_LED_NUM + PUB_LED_NUM;

	// 电度资源
	fh.dd_addr = FILE_ADDR_ALGIN(fh.led_addr + fh.led_num * sizeof(struct led_rsc));
	fh.dd_num = SW_DD_NUM_ALL;

	// 得到文件长度
	file_length = FILE_ADDR_ALGIN(fh.dd_addr + fh.dd_num * sizeof(struct dd_rsc));
	
	// 分配并初始化空间
	p = rt_malloc(file_length + 2); //加crc长度
	if(!p)
	{
		return -1;

	}
	memset(p,0,file_length);
	
	// 写入文件头
	memcpy(p,(char *)&fh,sizeof(fh));
	
	// 写公共遥信
	for(i=0; i<fh.pub_di_num; i++)
	{
		memset(&disrc,0,sizeof(disrc));
		
		if (i < PUB_DI_NUM)
		{
			disrc.is_real = 1;
			disrc.indexno = i+1;
			strncpy(disrc.name,g_pub_di_name[i],EQU_CFG_NAME_LEN);
			disrc.name[EQU_CFG_NAME_LEN-1] = 0;
		}
		else
		{
			disrc.is_real = 0;
			disrc.indexno = i+1; 
			j= i+EV_SW_NUM-PUB_DI_NUM;
			strncpy(disrc.name,tAllSOE[j].strName,EQU_CFG_NAME_LEN);			
			disrc.name[EQU_CFG_NAME_LEN-1] = 0;			
		}		
		memcpy(p + fh.pub_di_addr + i*sizeof(disrc), (char *)&disrc, sizeof(disrc));		
	}

	// 写公共遥控
	for(i=0; i<fh.pub_do_num; i++)
	{
		memset(&dosrc,0,sizeof(dosrc));

		dosrc.is_real = 1;
		dosrc.indexno = i+1;
		strncpy(dosrc.name,g_pub_do_name[i],EQU_CFG_NAME_LEN);
		dosrc.name[EQU_CFG_NAME_LEN-1] = 0;
		
		memcpy(p + fh.pub_do_addr + i*sizeof(dosrc), (char *)&dosrc, sizeof(dosrc));		
	}

	// 写公共遥测
	for(i=0; i<fh.pub_ac_num; i++)
	{
		memset(&acsrc,0,sizeof(acsrc));
		
		acsrc.is_real = i<PUB_AC_NUM ? 1:0;
		acsrc.indexno = i+1;
		acsrc.unit = g_pub_ac_desc[i].unit;
		acsrc.unit_angle = g_pub_ac_desc[i].unit_angle;
		acsrc.normal = g_unit[g_pub_ac_desc[i].unit].normal;
		strncpy(acsrc.name,g_pub_ac_desc[i].name,EQU_CFG_NAME_LEN);
		acsrc.name[EQU_CFG_NAME_LEN-1] = 0;

		memcpy(p + fh.pub_ac_addr + i*sizeof(acsrc), (char *)&acsrc, sizeof(acsrc));		
	}	

	// 写开关遥信
	for(i=0; i<fh.sw_di_num; i++)
	{
		memset(&disrc,0,sizeof(disrc));
		
		if (i < SW_DI_NUM)
		{
			disrc.is_real = 1;
			disrc.indexno = i+1;
			strncpy(disrc.name,g_sw_di_name[i],EQU_CFG_NAME_LEN);
			disrc.name[EQU_CFG_NAME_LEN-1] = 0;
		}
		else
		{
			disrc.is_real = 0;
			disrc.indexno = i+1;
			strncpy(disrc.name,tAllSOE[disrc.indexno-SW_DI_NUM-1].strName,EQU_CFG_NAME_LEN);
			disrc.name[EQU_CFG_NAME_LEN-1] = 0;
		}
		memcpy(p + fh.sw_di_addr + i*sizeof(disrc), (char *)&disrc, sizeof(disrc));		
	}

	// 写开关遥控
	for(i=0; i<fh.sw_do_num; i++)
	{
		memset(&dosrc,0,sizeof(dosrc));

		dosrc.is_real = 1;
		dosrc.indexno = i+1;
		strncpy(dosrc.name,g_sw_do_name[i],EQU_CFG_NAME_LEN);
		dosrc.name[EQU_CFG_NAME_LEN-1] = 0;

		memcpy(p + fh.sw_do_addr + i*sizeof(dosrc), (char *)&dosrc, sizeof(dosrc));		
	}

	// 写开关遥测
	for(i=0; i<fh.sw_ac_num; i++)
	{
		memset(&acsrc,0,sizeof(acsrc));
		
		acsrc.is_real = i<SW_AC_NUM ? 1:0;
		acsrc.indexno = i+1;
		acsrc.unit = g_sw_ac_desc[i].unit;
		acsrc.unit_angle = g_sw_ac_desc[i].unit_angle;
		acsrc.normal = g_unit[g_sw_ac_desc[i].unit].normal;
		strncpy(acsrc.name,g_sw_ac_desc[i].name,EQU_CFG_NAME_LEN);
		acsrc.name[EQU_CFG_NAME_LEN-1] = 0;
		memcpy(p + fh.sw_ac_addr + i*sizeof(acsrc), (char *)&acsrc, sizeof(acsrc));		
	}
	// 写单位描述
	for(i=0; i<fh.unit_num; i++)
	{
		memset(&unitsrc,0,sizeof(unitsrc));
		
		strncpy(unitsrc.name,g_unit[i].name,8);
		unitsrc.name[8-1] = 0;
		memcpy(p + fh.unit_addr+ i*sizeof(unitsrc), (char *)&unitsrc, sizeof(unitsrc));
	}

	// 写LED资源
	for(i=0; i<fh.led_num; i++)
	{
		memset(&ledsrc,0,sizeof(ledsrc));

		// 先填写公共LED资源
		if (i < PUB_LED_NUM)
		{
			ledsrc.owner = 0;
			ledsrc.indexno = i+1;
			strncpy(ledsrc.name, g_pub_led_name[i], EQU_CFG_NAME_LEN);
			ledsrc.name[EQU_CFG_NAME_LEN-1] = 0;
		}
		else
		{
			ledsrc.owner = 1;
			ledsrc.indexno = i+1-PUB_LED_NUM;
			strncpy(ledsrc.name,g_sw_led_name[i-PUB_LED_NUM],EQU_CFG_NAME_LEN);
			ledsrc.name[EQU_CFG_NAME_LEN-1] = 0;			
		}
		memcpy(p + fh.led_addr + i*sizeof(ledsrc), (char *)&ledsrc, sizeof(ledsrc));		
	}

	// 写开关电度
	for(i=0; i<fh.dd_num; i++)
	{
		memset(&ddsrc,0,sizeof(ddsrc));
		
		ddsrc.is_real = 1;
		ddsrc.indexno = i+1;
		ddsrc.unit = g_dd_desc[i].unit;
		ddsrc.unit_angle = g_dd_desc[i].unit_angle;
		ddsrc.normal = g_unit[g_dd_desc[i].unit].normal;
		strncpy(ddsrc.name,g_dd_desc[i].name,EQU_CFG_NAME_LEN);
		ddsrc.name[EQU_CFG_NAME_LEN-1] = 0;
		memcpy(p + fh.dd_addr + i*sizeof(ddsrc), (char *)&ddsrc, sizeof(ddsrc));		
	}


	// 创建描述文件
	pfile = rt_file_open("/tmp/"FILE_NAME_RSC,O_CREAT|O_RDWR|O_TRUNC,0);
	if(IS_ERR(pfile))
	{
		rt_free(p);
		return -10;
	}

	// 计算CRC
	g_crc_rsc = CrcStr(p,file_length);
	memcpy(p+file_length,&g_crc_rsc,2);
	
	pos = 0;
	rt_file_write(pfile,p,file_length + 2,&pos);

	rt_file_close(pfile,0);

	rsc_contrast.version = fh.cfh.version;
	rsc_contrast.signature = fh.cfh.signature;
	rsc_contrast.length = file_length+2;
	rsc_contrast.crc = g_crc_rsc;

	rt_free(p);
	
	return 0;
}


 int tbl_init(void)
{
	u32 len;
	u8 *buf;
	struct table_file_head_data *brh;

	struct file * pfile;
	loff_t pos;

	// 打开文件
	pfile = rt_file_open("/app/data/iectable.bin",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);

	// 检查CRC
	g_crc_rectable = CrcStr(buf,len-2);

	if(g_crc_rectable != *(u16*)(buf+len-2))
	{
		rt_free(buf);
		return -4;
	}

	// 检查文件签名
	brh = (struct table_file_head_data*)buf;
	if(brh->cfh.signature != SIG_TABLE_FILE)
	{
		rt_free(buf);
		return -5;
	}

	//比对资源表文件
	if ((brh->rsc_version != rsc_contrast.version)
	|| (brh->rsc_signature!= rsc_contrast.signature)
	|| (brh->rsc_length!= rsc_contrast.length)
	|| (brh->rsc_crc!= rsc_contrast.crc))
	{
		rt_printf("iec_version=%4x\trsc_version=%4x\r\n",brh->rsc_version, rsc_contrast.version);
		rt_printf("iec_signature=%4x\trsc_signature=%4x\r\n",brh->rsc_signature, rsc_contrast.signature);
		rt_printf("iec_length=%4x\trsc_length=%4x\r\n",brh->rsc_length, rsc_contrast.length);
		rt_printf("iec_crc=%4x\trsc_crc=%4x\r\n",brh->rsc_crc, rsc_contrast.crc);

		rt_free(buf);
		return -6;
	}
	
	g_table_head = (struct table_file_head_data *)buf;
	g_di_table = (struct di_table *)(buf + brh->di_addr);
	g_di_merge_table = (struct di_merge_table *)(buf + brh->dimerge_addr);
	g_di_db_table = (struct di_db_table *)(buf + brh->di_db_addr);
	g_do_table = (struct do_table *)(buf + brh->do_addr);
	g_ac_table = (struct ac_table *)(buf + brh->ac_addr);
	g_sz_table = (struct sz_table *)(buf + brh->sz_addr);
	g_dd_table = (struct dd_table *)(buf + brh->dd_addr);
#ifdef FUN_DIMER_LINK
	g_di_info_merge_table = (struct di_table *)FILE_ADDR_ALGIN(buf + brh->di_db_addr+g_table_head->di_db_num*sizeof(struct di_db_table));
	g_di_info_merge_num = (brh->do_addr - brh->di_db_addr)/sizeof(struct di_table);
	rt_printf("---------g_di_info_merge_table=%x,g_di_info_merge_num=%d\r\n",(u32)g_di_info_merge_table-(u32)buf,g_di_info_merge_num);
#endif
#ifdef FUN_JSON_FILE
	//tbl_json_file_init();
#endif

	//分配遥控信息结构
	if(g_table_head->do_num)
	{
		len = g_table_head->do_num * sizeof(REMOTEYKSTATUS);
		g_yk_info = (REMOTEYKSTATUS *)rt_malloc(len);
		if(g_yk_info == NULL)
		{
			return -7;
		}
		memset(g_yk_info,0,len);
	}
	hs_write_iec_crc();
	return tbl_link_init();
}

#ifdef FUN_JSON_FILE
int tbl_json_file_init(void)
{
	
	int i,j;
	unsigned int file_len=0;
	unsigned char *p,*p_file;
	loff_t pos;
	struct timespec ts;
	struct rtc_time_t tm;
	char name[64];
	char dir[64];
	struct file * handle;
#ifdef FUNC_JSON_UTF8_FORMAT
	int k=0;
	u8 utf8[3];
	unsigned char *file_utf;
	u32 utf8_code;
	u16 gb2312_code;
#endif	

	sprintf(dir,"%s/soeIndex.json",HF_IEC_TAB_DIR);

	rt_file_del(dir);

	// 打开文件
	handle = rt_file_open(dir,O_CREAT|O_RDWR ,0);

#if 0
	if(IS_ERR(handle))
	{
		handle = 0;
		rt_file_deldir(HF_IEC_TAB_DIR);
	}
	else
	{
		//得到文件长度
		rt_file_llseek(handle,0,SEEK_END);
		file_len= handle->f_pos;			
		rt_file_llseek(handle,0,SEEK_SET);
		//文件长度为0
		if(file_len && !hs_read_iec_crc())	
		{
			rt_file_close(handle,0);
			return 0;
		}	
	}
#endif	

	if(!g_di_table)
		return -1;

	rt_file_mkdir(HF_IEC_TAB_DIR);
	file_len = HF_IEC_TAB_HEAD_LEN+HF_IEC_TAB_ITEM_LEN*g_table_head->di_num+8;

	// 分配并初始化空间
	p_file = rt_malloc(file_len); 
	if(!p_file)
	{
		return -2;
	}
	memset(p_file,0,file_len);
	p=p_file;

	//获取当前时间
	clk_time_get(&ts);
	timespec_to_rtc(ts,&tm,0);

	j=sprintf(p,"{\r\n\t\"文件描述\":\"原始点表索引\",\r\n");
	p += j;

	j=sprintf(p,"\t\"修改时间\":\"%04d-%02d-%02d %02d:%02d:%02d\",\r\n",	
								tm.year+2000,
								tm.month,
								tm.day,
								tm.hour,
								tm.min,
								tm.ms/1000);
	p += j;	

	j=sprintf(p,"\t\"总数量\":\"%d\",\r\n",g_table_head->di_num);
	p += j;	

	j=sprintf(p,"\t\"index_list\":[");
	p += j;	

	for(i=0;i<g_table_head->di_num;i++)
	{
		tbl_getname(RES_TYPE_YX,i,name);

		if(i == g_table_head->di_num-1)
		{
			j=sprintf(p,"{\r\n\t\"id\": %d,\r\n\t\"name\": \"%s\"\r\n\t}",i,name);
		}
		else
		{
			j=sprintf(p,"{\r\n\t\"id\": %d,\r\n\t\"name\": \"%s\"\r\n\t},",i,name);
		}
		p += j;	

		if(i!=g_table_head->di_num-1)
		{
			j=sprintf(p," ");
			p += j;	
		}
	}

	j=sprintf(p,"]\r\n}");
	p += j;	

	file_len = p-p_file;
	
	pos = 0;

#ifdef FUNC_JSON_UTF8_FORMAT
	file_utf = rt_malloc(file_len*3); 
	if(!file_utf)
	{
		rt_free(p_file);
		return -3;
	}

	for(i=0;i<file_len;) 
	{
		if(p_file[i] <= 0x80)  //非汉字
		{	
			file_utf[k] = p_file[i];
			k++;
			i++;
			continue;
		}
		
		gb2312_code = p_file[i+1]|(p_file[i]<<8);
		utf8_code = GetHzUtf8ByFontLib(gb2312_code);
		if(utf8_code == 0)
		{
			rt_err_set(ERR_CODE_INIT_SOFTWARE,0);
			return false;
		}
		utf8[0] = (utf8_code>>16)&0xFF;
		utf8[1] = (utf8_code>>8)&0xFF;
		utf8[2] = utf8_code&0xFF;
		memcpy(&file_utf[k],utf8,sizeof(utf8));
		k += 3;
		i += 2;
	}

	if(rt_file_write(handle,file_utf,k,&pos)!=k)
	{
		rt_free(p_file);
		rt_free(file_utf);
		return -4;
	}
#else
	if(rt_file_write(handle,p_file,file_len,&pos)!=file_len)
	{
		rt_free(p_file);
		return -4;
	}
#endif

	rt_file_close(handle,0);

	rt_free(p_file);

#ifdef FUNC_JSON_UTF8_FORMAT
	rt_free(file_utf);
#endif

	return 0;
}
#endif

int tbl_exit(void)
{
	tbl_link_exit();

	if(g_yk_info)
	{
		rt_free(g_yk_info);
	}
	
	if(g_table_head && (g_table_head != &g_table_head_null))
	{
		rt_free(g_table_head);
	}

	return 0;
}

int  tbl_cp2index(u16  cp)
{
	int i;
	
	// 获取点号在转发表中的位置
	for(i=0;i<g_table_head->di_num;i++)
	{
		if(cp == g_di_table[i].cp)
		{
			return i;
		}
	}

	return -1;
}

u8  tbl_get_dpi(int  i) // 判断点号是否是双点
{
	int j;
	if(i < 0)
	{
		return 0;
	}	
#ifdef IECTABLE_NEWDPI_V106
	return g_di_table[i].dpi;
#else
	if(g_di_table[i].owner == SWITCH_NUM_EXT)
	{
		return 1;	
	}
#endif	// 备用点,可能对应双点与合并点,也可能仅占位置
	// 双点
	for(j=0;j<g_table_head->di_db_num;j++)  
	{
		if(g_di_table[i].cp == g_di_db_table[j].cp)  
		{
			return 1;							
		}
	}	
	return 0;

}

u8  tbl_get_yx(int  i,int bDPI)
{
	int j;
	u8 v;
	bool b_siq=false;
#ifdef FUNC_JX_YX_BEFORE
	static u8 v_tmp[PUB_DI_NUM+SW_DI_NUM+EV_PUB_END]={0};
#endif

	if(i < 0)
	{
		return 0;
	}
	
	// 单点
	if(g_di_table[i].indexno>0)  
	{
		v=GetRmtYxVal(g_di_table[i].owner,g_di_table[i].indexno);
		if(v&0x80)
		{
			#ifdef IEC_QDS_HAVE
				b_siq = true;
				v=(v&0x7f);
			#endif
		}
	
		
#ifndef IECTABLE_NEWDPI_V106   //老版本，特殊处理
		//上送到主站的开关属性为31的点上送为双点
		if(g_di_table[i].owner == SWITCH_NUM_EXT)
		{
			if(g_di_table[i].is_inverse)
			{
				v = (v==2)?1:2;
			}
		}
		else
#endif
		{
			v = g_di_table[i].is_inverse ? ((~v)&0x03) : v;

			// 如果需要双点转单点，除了0x02外，其余都为0
			if(bDPI == 0)
			{	
				v = (v==0x02) ? 1 : 0;
			}
		}

#ifdef FUNC_JX_YX_BEFORE
		if(!g_run_stu.bjx)
		{
			v_tmp[i] = (b_siq?(v|0x80):v);
		}
		else
		{
			return v_tmp[i];
		}
#endif

		return (b_siq?(v|0x80):v);	
	}
	
	// 备用点,可能对应双点与合并点,也可能仅占位置
	// 双点
	for(j=0;j<g_table_head->di_db_num;j++)  
	{
		if(g_di_table[i].cp == g_di_db_table[j].cp)  
		{
			v=plc_db_value(j); 

			#if defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020
			{
				int id1,id2;
				id1 = g_di_db_table[j].no[0]&0xff;
				id2 = g_di_db_table[j].no[1]&0xff;

				if(((id1 == (SW_DI_BHTT+1))&&(id2 == (SW_DI_FA_TT+1)))
						||((id2 == (SW_DI_BHTT+1))&&(id1 == (SW_DI_FA_TT+1))))
				{
					v = (v == 0)?1:2;
				}
			}
			#endif
		
			
			if(!bDPI)
			{	
				v = (v == SW_DI_TYPE_ON);
			}
			
#ifdef FUNC_JX_YX_BEFORE
			if(!g_run_stu.bjx)
			{
				v_tmp[i] = v;
			}
			else
			{
				return v_tmp[i];
			}
#endif
			return v;							
		}
	}					

	// 合并点
	for(j=0;j<g_table_head->dimerge_num;j++) 
	{
		if(g_di_table[i].cp == g_di_merge_table[j].cp) 
		{
			v = g_plc[g_plc_merge_index+j].result ? 1:0;
			if(bDPI)
			{	
				v+=1;  
			}
			
#ifdef FUNC_JX_YX_BEFORE
			if(!g_run_stu.bjx)
			{
				v_tmp[i] = v;
			}
			else
			{
				return v_tmp[i];
			}
#endif
			return v;
		}
	}
	// 备用点，仅占位置
	v=0;
	if(bDPI)
	{	
		v+=1;  
	}
	
#ifdef FUNC_JX_YX_BEFORE
	if(!g_run_stu.bjx)
	{
		v_tmp[i] = v;
	}
	else
	{
		return v_tmp[i];
	}
#endif
	return v;
}


// 远动遥信值
int tbl_yd_yx(u16 begin,u16 num,u8 * yx_buf)
{
	u8 yx;
	u8 sw,no;
	u16 i,j,k ;
	u16 cnt,cnt_begin,cnt_yx;

	// 每个遥信占2bits，每帧最多200字节，允许800个遥信(可以超过一个合并点20个遥信，5个字节)。
	if(num > 800)
	{
		num = 800;
	}

	cnt_begin = 0;
	cnt_yx = 0;
	for(i=0; i<g_table_head->di_num; i++)
	{
		// 寻找起始位置
		if(cnt_begin < begin)
		{
			// 不过单点、双点、合并点、备用点，都在g_di_table占有位置，首先加1
			cnt_begin++;
			
			if(g_di_table[i].indexno)
			{
				continue;
			}
			// 双点
			cnt = 0;
			for(j=0; j<g_table_head->di_db_num; j++) 
			{
				if(g_di_db_table[j].cp == g_di_table[i].cp)
				{
					cnt = 2;
					break;
				}
			}

			if(cnt)
			{
				cnt_begin += cnt;
				continue;
			}

			// 合并点
			cnt = 0;
			for(j=0;j<g_table_head->dimerge_num;j++) 
			{
				if(g_di_merge_table[j].cp == g_di_table[i].cp)
				{
					for(k=0;k<MIX_YX_NUMBER;k++)
					{
						if(g_di_merge_table[j].no[k] == 0)
						{
							break;
						}
						cnt++;
					}
					break;
				}
				cnt_begin += cnt;
			}

			if(cnt_begin > begin)
			{
				rt_printf("tbl_yd_yx error:cnt_begin=%d,begin=%d.\r\n",cnt_begin,begin);
				return -1;
			}
			continue;
		}

		// 此处开始，获取遥信值
		if(cnt_yx >= num)
		{
			return cnt_yx;
		}
		// 单点
		yx = tbl_get_yx(i,1);
		yx_buf[cnt_yx/4] |= yx<<((cnt_yx%4)*2);
		cnt_yx++;
		
		if(g_di_table[i].indexno)
		{
			continue;
		}

		// 双点
		cnt = 0;
		for(j=0; j<g_table_head->di_db_num; j++) 
		{
			if(g_di_db_table[j].cp == g_di_table[i].cp)
			{
				for (k=0; k<2; k++)
				{
					sw = (u8)(g_di_db_table[j].no[k]>>8);
					no = (u8)(g_di_db_table[j].no[k]);
					yx=GetRmtYxVal(sw,no);
					yx = g_di_db_table[j].is_inv[k] ? ((~yx)&0x03) : yx; // 取反
					//yx += 1; 									// 变双点
					yx_buf[cnt_yx/4] |= yx<<((cnt_yx%4)*2);
					cnt_yx++;
					cnt++;
				}

				break;
			}
		}

		if(cnt)
		{
			continue;
		}
		
		// 合并点
		cnt = 0;
		for(j=0; j<g_table_head->dimerge_num; j++) 
		{
			if(g_di_merge_table[j].cp == g_di_table[i].cp)
			{
				
				for (k=0; k<MIX_YX_NUMBER; k++)
				{
					// 组合点号为空代表结束，退出。
					if(g_di_merge_table[j].no[k] == 0)
					{
						break;
					}
					
					no=g_di_merge_table[j].no[k]&0xff;
					sw=(g_di_merge_table[j].no[k]>>8)&0xff;	
					
					yx=GetRmtYxVal(sw,no);
					yx = g_di_merge_table[j].is_inv[k] ? ((~yx)&0x03) : yx; // 取反
				//	yx += 1; 									// 变双点
					yx_buf[cnt_yx/4] |= yx<<((cnt_yx%4)*2);
					cnt_yx++;
					cnt++;
				}
				break;
			}
		}
	}

	return cnt_yx;
}


// 远动遥测值
int tbl_yd_yc(u16 begin,u16 num,u8 * yc_buf)
{
	u8 sw,no;
	u16 i;
	u16 cnt_yc;
	long val,ang;
	int pCal;

	// 每个遥测占9bytes，每帧最多200字节，允许 200/9 个遥测。
	if(num > 200/9)
	{
		num = 200/9;
	}
	cnt_yc = 0;
	for(i=begin; (i<g_table_head->ac_num) && (cnt_yc < num); i++,cnt_yc++)
	{
			sw = g_ac_table[i].owner;
			no = g_ac_table[i].indexno - 1;
			
			if (sw == 0)
			{
				val=g_sw_pub.ac_in[no];
				if(no<PUB_AC_NUM)
				{
					ang=g_ui[no].p;
					if(g_ui[no].chn_index!=CFG_ADC_CHANNEL_ZERO)
					{
						pCal = 0x1;
					}
					else if(g_ui[no].ui_base_make!=-1)
					{
						pCal = 0x2;
					}
					else
					{
						pCal = 0x4;
					}
				}	
				else
				{
					ang=ANGEL_INVALID;
					pCal=0x2;
				}
				
				if(g_unit[g_pub_ac_desc[no].unit].zero>0&&_AbsL(val)<g_unit[g_pub_ac_desc[no].unit].zero && pRunSet->bTT_RET_ZERO)
				{
					val=0;
					ang=ANGEL_INVALID;
				}					
	
				yc_buf[cnt_yc*9] = pCal;
				yc_buf[cnt_yc*9+1] = val;
				yc_buf[cnt_yc*9+2] = (val >> 8);
				yc_buf[cnt_yc*9+3] = (val >> 16);
				yc_buf[cnt_yc*9+4] = (val >> 24);
				yc_buf[cnt_yc*9+5] =  ang;
				yc_buf[cnt_yc*9+6] = (ang >> 8);
				yc_buf[cnt_yc*9+7] = (ang >> 16);
				yc_buf[cnt_yc*9+8] = (ang >> 24);

			}
			else if (sw <= SWITCH_NUM_EXT)
			{
				int index_begin;				
				sw--;
				index_begin = UI_SW_INDEX_BEGIN(sw);
				
				val = g_sw[sw].ac_in[no];
 				if(no<SW_AC_NUM)
				{
					ang=g_ui[index_begin+no].p;
					if(g_ui[index_begin+no].chn_index!=CFG_ADC_CHANNEL_ZERO)
					{
						pCal = 0x1;
					}
					else if(g_ui[index_begin+no].ui_base_make!=-1)
					{
						pCal = 0x2;
					}
					else
					{
						pCal = 0x4;
					}

				}
				else
				{
					pCal= 0x2;
					ang = ANGEL_INVALID;
				}
					
				if(g_unit[g_sw_ac_desc[no].unit].zero>0&&_AbsL(val)<g_unit[g_sw_ac_desc[no].unit].zero && pRunSet->bTT_RET_ZERO)
				{
					val=0;
					ang=ANGEL_INVALID;
				}
				
				yc_buf[cnt_yc*9] = pCal;
				yc_buf[cnt_yc*9+1] = val;
				yc_buf[cnt_yc*9+2] = (val >> 8);
				yc_buf[cnt_yc*9+3] = (val >> 16);
				yc_buf[cnt_yc*9+4] = (val >> 24);
				yc_buf[cnt_yc*9+5] =  ang;
				yc_buf[cnt_yc*9+6] = (ang >> 8);
				yc_buf[cnt_yc*9+7] = (ang >> 16);
				yc_buf[cnt_yc*9+8] = (ang >> 24); 
			}
 		}

 	return cnt_yc;
}


// 远动电度值
int tbl_yd_dd(u16 begin,u16 num,u8 * dd_buf)
{
	u8 sw,no;
	u16 i;
	u16 cnt_dd;
	long val,ang;
	int pCal;

	// 每个遥测占9bytes，每帧最多200字节，允许 200/9 个遥测。
	if(num > 200/9)
	{
		num = 200/9;
	}
	cnt_dd = 0;
	for(i=begin; (i<g_table_head->dd_num) && (cnt_dd < num); i++,cnt_dd++)
	{
			sw = g_dd_table[i].owner;
			no = g_dd_table[i].indexno - 1;
			
			if (sw == 0)
			{
				pCal = 0x2;
				val=0;
				ang=ANGEL_INVALID;
				
				dd_buf[cnt_dd*9] = pCal;
				dd_buf[cnt_dd*9+1] = val;
				dd_buf[cnt_dd*9+2] = (val >> 8);
				dd_buf[cnt_dd*9+3] = (val >> 16);
				dd_buf[cnt_dd*9+4] = (val >> 24);
				dd_buf[cnt_dd*9+5] =  ang;
				dd_buf[cnt_dd*9+6] = (ang >> 8);
				dd_buf[cnt_dd*9+7] = (ang >> 16);
				dd_buf[cnt_dd*9+8] = (ang >> 24);

			}
			else if (sw <= SWITCH_NUM_EXT)
			{
				sw--;

				pCal = 0x2;
				val = (long)(g_sw[sw].dd[no].fv*Q16_BASE);
				ang=ANGEL_INVALID;
				
				dd_buf[cnt_dd*9] = pCal;
				dd_buf[cnt_dd*9+1] = val;
				dd_buf[cnt_dd*9+2] = (val >> 8);
				dd_buf[cnt_dd*9+3] = (val >> 16);
				dd_buf[cnt_dd*9+4] = (val >> 24);
				dd_buf[cnt_dd*9+5] =  ang;
				dd_buf[cnt_dd*9+6] = (ang >> 8);
				dd_buf[cnt_dd*9+7] = (ang >> 16);
				dd_buf[cnt_dd*9+8] = (ang >> 24); 
			}
 		}

 	return cnt_dd;
}

/*------------------------------ 内部函数 -------------------------------------
内部函数以下划线‘_’开头，不需要检查参数的合法性.
*/


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

	if(index == 0)
	{
		sprintf(name,"备用点");
		return;
	}
	
	index--;
	
	if(owner == 0)
	{
		if(index < PUB_DI_NUM)
		{
			strcpy(name, g_pub_di_name[index]);
		}
		else
		{
			index -= PUB_DI_NUM;
			strcpy(name, tAllSOE[index  + EV_SW_NUM].strName);
		}
	}
	else
	{
		char swstr[12];
		strcpy(swstr,"");
		#if SWITCH_NUM_MAX!=1
		sprintf(swstr,"开关%02d",owner);
		#endif
		
		if(index < SW_DI_NUM)
		{
			sprintf(name,"%s%s", swstr,g_sw_di_name[index]);
		}
		else
		{
			sprintf(name, "%s%s", swstr,tAllSOE[index - SW_DI_NUM].strName);		
		}
	}
}


void tbl_getacname(WORD owner,WORD index,char *name)
{

	if(owner==0)
	{
		strcpy(name, g_pub_ac_desc[index-1].name);
	}
	else
	{
		#if SWITCH_NUM_MAX!=1
		sprintf(name,"开关%d_%s",owner, g_sw_ac_desc[index-1].name);
		#else
		sprintf(name,"%s", g_sw_ac_desc[index-1].name);
		#endif
	}
}


void tbl_getddname(WORD owner,WORD index,char *name)
{
	strcpy(name, g_dd_desc[index-1].name);
}


void tbl_getdoname(WORD owner,WORD index,char *name)
{
	if(owner==0)
	{
		sprintf(name,"%s", g_pub_do_name[index-1]);
	}
	else
	{
		#if SWITCH_NUM_MAX!=1
		sprintf(name,"开关%d%s",owner, g_sw_do_name[index-1]);
		#else
		sprintf(name,"%s", g_sw_do_name[index-1]);
		#endif
	}
}


int tbl_get_sz_index_yc(u16 tbl_index)
{
	return tbl_index;
}

int tbl_get_sz_index_yk(u16 tbl_index)
{
	int i;
	int sz_index;

	sz_index = 0;
	for(i=0; i< tbl_index; i++)
	{
		sz_index++;
		if(g_do_table[i].indexno[1])
		{
			sz_index++;
		}
	}
	
	return sz_index;
}

int tbl_get_sz_index_yx(u16 tbl_index)
{
	int i,j,k;
	int sz_index,cnt;

	sz_index = 0;
	for(i=0; i<tbl_index; i++)
	{
		// 不过单点、双点、合并点、备用点，都在g_di_table占有位置，首先加1
		sz_index++;
		if(g_di_table[i].indexno)
		{
			continue;
		}
		// 双点
		cnt = 0;
		for(j=0; j<g_table_head->di_db_num; j++) 
		{
			if(g_di_db_table[j].cp == g_di_table[i].cp)
			{
				cnt = 2;
				break;
			}
		}

		if(cnt)
		{
			sz_index += cnt;
			continue;
		}

		// 合并点
		cnt = 0;
		for(j=0;j<g_table_head->dimerge_num;j++) 
		{
			if(g_di_merge_table[j].cp == g_di_table[i].cp)
			{
				for(k=0;k<MIX_YX_NUMBER;k++)
				{
					if(g_di_merge_table[j].no[k] == 0)
					{
						break;
					}
					cnt++;
				}
				break;
			}
		}
		if(cnt)
		{
			sz_index += cnt;
			continue;
		}
	}

	return sz_index;
}

int tbl_getname_sz(WORD tbl_type, WORD tbl_index,char *name)
{
	int i;
	
	for(i=0; i< g_table_head->sz_num;i++)
	{
		if(tbl_type == g_sz_table[i].type && tbl_index == g_sz_table[i].index)
		{
			strcpy(name,(char *)&g_sz_table[g_table_head->sz_num] + g_sz_table[i].offset);
			return 0;
		}
	}

	return -1;
}
void tbl_getname(WORD tbl_type, WORD tbl_index,char *name)
{
	int sz_index;

	if(tbl_type == RES_TYPE_YX)

	{
		sz_index =  tbl_get_sz_index_yx(tbl_index);
		if(tbl_getname_sz(tbl_type,sz_index,name) < 0)
		{
			tbl_getdiname(g_di_table[tbl_index].owner,g_di_table[tbl_index].indexno,name);
		}
	}
	else if(tbl_type == RES_TYPE_YC)

	{
		sz_index =  tbl_get_sz_index_yc(tbl_index);
		if(tbl_getname_sz(tbl_type,sz_index,name) < 0)
		{
			tbl_getacname(g_ac_table[tbl_index].owner,g_ac_table[tbl_index].indexno,name);
		}
	}
	else if(tbl_type == RES_TYPE_YK)
	{
		sz_index =  tbl_get_sz_index_yk(tbl_index);
		if(tbl_getname_sz(tbl_type,sz_index,name) < 0)
		{
			tbl_getdoname(g_do_table[tbl_index].owner,g_do_table[tbl_index].indexno[0],name);
		}
	}
	else if(tbl_type == RES_TYPE_DD)

	{
		sz_index =  tbl_index;
		if(tbl_getname_sz(tbl_type,sz_index,name) < 0)
		{
			tbl_getddname(g_ac_table[tbl_index].owner,g_ac_table[tbl_index].indexno,name);
		}
	}
}


void _tbl_link_ch_to_text( unsigned char ch,char *buf) 
{
	if( ch == 0  || ch == 128)
		sprintf(buf,"无");
	else if(ch < 128)
		sprintf(buf,"ET_%02d",ch);
	else
		sprintf(buf,"RS_%02d",ch-128);

	return;
}

int tbl_printf(void)
{
	int i, j;
	u8 owner, indexno;
	char name[64];
	
	rt_printf("di单点点表:\r\n");
	rt_printf("cp\tsw\tno\tis_inverse\tDPI\r\n");
	for(i=0; i<g_table_head->di_num; i++)
	{
//		tbl_getdiname(g_di_table[i].owner,g_di_table[i].indexno,name);
		tbl_getname(RES_TYPE_YX,i,name);
		rt_printf("%x,\t%d,\t%d,\t%d,\t\t%d,\t%s\r\n",
			g_di_table[i].cp,
			g_di_table[i].owner,
			g_di_table[i].indexno,
			g_di_table[i].is_inverse,
			
#ifdef IECTABLE_NEWDPI_V106
			g_di_table[i].dpi,
#else
			0,
#endif
			name);
	}

	rt_printf("\r\ndi双点点表:\r\n");
	rt_printf("no\towner\tindexno\tis_inverse\r\n");
	for(i=0; i<g_table_head->di_db_num; i++)
	{
		owner = (g_di_db_table[i].no[0]&0xFF00)>>8;
		indexno = g_di_db_table[i].no[0];
		
		tbl_getdiname(owner,indexno,name);
		rt_printf("%x,\t%d,\t%d,\t%d,\t%s\r\n",
			g_di_db_table[i].cp,
			owner,
			indexno,
			g_di_db_table[i].is_inv[0],
			name);
			
		owner = (g_di_db_table[i].no[1]&0xFF00)>>8;
		indexno = g_di_db_table[i].no[1];

		tbl_getdiname(owner,indexno,name);
		rt_printf("%x,\t%d,\t%d,\t%d,\t%s\r\n",
			g_di_db_table[i].cp,
			owner,
			indexno,
			g_di_db_table[i].is_inv[1],
			name);
		rt_printf("\r\n");
	}

	rt_printf("di合并点表:\r\n");
	rt_printf("no\tinv_all\towner\tindex\tis_inv\tlink_ch\tlink_cp\r\n");
	for(i=0; i<g_table_head->dimerge_num; i++)
	{
		for (j=0; j<20; j++)
		{
			if(g_di_merge_table[i].no[j] == 0)
			{
				break;
			}
			owner = (g_di_merge_table[i].no[j])>>8;
			indexno = g_di_merge_table[i].no[j];

			tbl_getdiname(owner,indexno,name);
			rt_printf("%x,\t%d,\t%d,\t%d,\t%d,\t%x,\t%x,\t%s\r\n",
			g_di_merge_table[i].cp,
			g_di_merge_table[i].is_inv_all,
			owner,
			indexno,
			g_di_merge_table[i].is_inv[j],
#ifdef IECTABLE_NEWDPI_V106			
			g_di_merge_table[i].link_ch[j],			
			g_di_merge_table[i].link_cp[j],
#else
			0,0,
#endif			
			name);
		}
		
		rt_printf("\r\n");
	}

	rt_printf("\r\n\r\n");
	rt_printf("do点表:\r\n");
	rt_printf("no\towner\tindex0\tindex1\tlnk_ch\tlnk_cp\r\n");
	for(i=0; i<g_table_head->do_num; i++)
	{
		//tbl_getdoname(g_do_table[i].owner,g_do_table[i].indexno[0],name);
		tbl_getname(RES_TYPE_YK,i,name);
		rt_printf("%x,\t%d,\t%d,\t%d,\t%d,\t%d,\t%s\r\n",
			g_do_table[i].cp,
			g_do_table[i].owner,
			g_do_table[i].indexno[0],
			g_do_table[i].indexno[1],
			g_do_table[i].link_ch,
			g_do_table[i].link_cp,
			name);
	}

	rt_printf("\r\nac点表:\r\n");
	rt_printf("no\towner\tindexno\trate\t\tnormal\t\tdead\t\tlnk_ch\tlnk_cp\r\n");
	for(i=0; i<g_table_head->ac_num; i++)
	{
		rt_printf("%x,\t%d,\t%d,",
			g_ac_table[i].cp,
			g_ac_table[i].owner,
			g_ac_table[i].indexno);
		rt_printf("\t%s,",q16_to_str(g_ac_table[i].rate));
		rt_printf("\t%s,",q16_to_str(g_ac_table[i].normal)),
		rt_printf("\t%s,",q16_to_str(g_ac_table[i].dead_value)),
		
		_tbl_link_ch_to_text(g_ac_table[i].link_ch,name);
		rt_printf("\t%s,",name),
		
		rt_printf("\t%04x,",g_ac_table[i].link_cp),

		//tbl_getacname(g_ac_table[i].owner,g_ac_table[i].indexno,name);
		tbl_getname(RES_TYPE_YC,i,name);
		rt_printf("\t%s\r\n",name);
	}
	
	rt_printf("\r\ndd点表:\r\n");
	rt_printf("no\towner\tindexno\trate\t\tnormal\t\tdead\t\tlnk_ch\tlnk_cp\r\n");
	for(i=0; i<g_table_head->dd_num; i++)
	{
		rt_printf("%x,\t%d,\t%d,",
			g_dd_table[i].cp,
			g_dd_table[i].owner,
			g_dd_table[i].indexno);
		rt_printf("\t%s,",q16_to_str(g_dd_table[i].rate));
		rt_printf("\t%s,",q16_to_str(g_dd_table[i].normal)),
		rt_printf("\t%s,",q16_to_str(g_dd_table[i].dead_value)),
		
		_tbl_link_ch_to_text(g_dd_table[i].link_ch,name);
		rt_printf("\t%s,",name),
		
		rt_printf("\t%04x,",g_dd_table[i].link_cp),

		//tbl_getddname(g_dd_table[i].owner,g_dd_table[i].indexno,name);
		tbl_getname(RES_TYPE_DD,i,name);
		rt_printf("\t%s\r\n",name);
	}	

	rt_printf("字符串表(%d):\r\n",g_table_head->sz_num);
	rt_printf("type\tindex\toffet\tname\r\n");
	for(i=0; i<g_table_head->sz_num; i++)
	{
		name[0] = 0;
		tbl_getname_sz(g_sz_table[i].type,g_sz_table[i].index,name);
		rt_printf("%d,\t%d,\t%d,\t%s\r\n",
			g_sz_table[i].type,
			g_sz_table[i].index,
			g_sz_table[i].offset,
			name);
	}

	return 0;
}

int tbl_printf_rsc(void)
{
	int i;

	u32 len;
	u16 crc;
	u8 *buf;
	struct rsc_file_head_data *brh;

	struct file * pfile;
	loff_t pos;

	// 打开文件
	pfile = rt_file_open("/tmp/"FILE_NAME_RSC,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);

	// 检查CRC
	crc = CrcStr(buf,len-2);
	if(crc != *(u16*)(buf+len-2))
	{
		rt_free(buf);
		return -4;
	}

	// 检查文件签名
	brh = (struct rsc_file_head_data*)buf;
	if(brh->cfh.signature != SIG_RSC_FILE)
	{
		rt_free(buf);
		return -5;
	}

	// 检查文件长度
	/*if(len < sizeof(*brh) + brh->br_num*sizeof(struct board_res)+ 2)
	{
		rt_free(buf);
		return -51; 	
	}*/

	g_rsc_head = (struct rsc_file_head_data *)buf;
	g_di_pub_rsc = (struct di_rsc *)(buf + brh->pub_di_addr);
	g_do_pub_rsc = (struct do_rsc *)(buf + brh->pub_do_addr);
	g_ac_pub_rsc = (struct ac_rsc *)(buf + brh->pub_ac_addr);
	g_di_sw_rsc = (struct di_rsc *)(buf + brh->sw_di_addr);
	g_do_sw_rsc = (struct do_rsc *)(buf + brh->sw_do_addr);
	g_ac_sw_rsc = (struct ac_rsc *)(buf + brh->sw_ac_addr);
	g_led_rsc =  (struct led_rsc *)(buf + brh->led_addr);
	g_unit_rsc = (struct unit_rsc *)(buf + brh->unit_addr);
	
	rt_printf("PUB di资源表:\r\n");
	rt_printf("no\tis_real\tindex\tname\r\n");
	for(i=0; i<g_rsc_head->pub_di_num; i++)
	{
		rt_printf("%d,\t%d,\t%d,\t%s,\r\n",i,
			g_di_pub_rsc[i].is_real,
			g_di_pub_rsc[i].indexno,
			g_di_pub_rsc[i].name);
	}

	rt_printf("PUB do资源表:\r\n");
	rt_printf("no\tis_real\tindex\tname\r\n");
	for(i=0; i<g_rsc_head->pub_do_num; i++)
	{		
		rt_printf("%d,\t%d,\t%d,\t%s,\r\n",
		i,g_do_pub_rsc[i].is_real,
		g_do_pub_rsc[i].indexno,
		g_do_pub_rsc[i].name);
	}
	
	rt_printf("PUB ac资源表:\r\n");
	rt_printf("no\tis_real\tindex\tname\tunit\tunit_angle\tnormal\r\n");
	for(i=0; i<g_rsc_head->pub_ac_num; i++)
	{		
		rt_printf("%d,\t%d,\t%d,\t%s,\t%d,\t%d,\t%d,\r\n",i,
		g_ac_pub_rsc[i].is_real,
		g_ac_pub_rsc[i].indexno,
		g_ac_pub_rsc[i].name,
		g_ac_pub_rsc[i].unit,
		g_ac_pub_rsc[i].unit_angle,
		g_ac_pub_rsc[i].normal);
	}

	rt_printf("SW di资源表:\r\n");
	rt_printf("no\tis_real\tindex\tname\r\n");
	for(i=0; i<g_rsc_head->sw_di_num; i++)
	{
		rt_printf("%d,\t%d,\t%d,\t%s,\r\n",i,
			g_di_sw_rsc[i].is_real,
			g_di_sw_rsc[i].indexno,
			g_di_sw_rsc[i].name);
	}

	rt_printf("SW do资源表:\r\n");
	rt_printf("no\tis_real\tindex\tname\r\n");
	for(i=0; i<g_rsc_head->sw_do_num; i++)
	{		
		rt_printf("%d,\t%d,\t%d,\t%s,\r\n",
		i,g_do_sw_rsc[i].is_real,
		g_do_sw_rsc[i].indexno,
		g_do_sw_rsc[i].name);
	}
	
	rt_printf("SW ac资源表:\r\n");
	rt_printf("no\tis_real\tindex\tname\tunit\tunit_angle\tnormal\r\n");
	for(i=0; i<g_rsc_head->sw_ac_num; i++)
	{		
		rt_printf("%d,\t%d,\t%d,\t%s,\t%d,\t%d,\t%d,\r\n",i,
		g_ac_sw_rsc[i].is_real,
		g_ac_sw_rsc[i].indexno,
		g_ac_sw_rsc[i].name,
		g_ac_sw_rsc[i].unit,
		g_ac_sw_rsc[i].unit_angle,
		g_ac_sw_rsc[i].normal);
	}

	rt_printf("LED资源表:\r\n");
	rt_printf("no\towner\tindex\tname\r\n");
	for(i=0; i<g_rsc_head->led_num; i++)
	{		
		rt_printf("%d,\t%d,\t%d,\t%s,\r\n",
		i,g_led_rsc[i].owner,
		g_led_rsc[i].indexno,
		g_led_rsc[i].name);
	}

	rt_printf("单位资源表:\r\n");
	for(i=0; i<g_rsc_head->unit_num; i++)
	{		
		rt_printf("%s\r\n",g_unit_rsc[i].name);
	}
	return 0;

}


void tbl_printf_cvs(void)
{
	int i;

	char name[64];
	
	rt_printf("\r\n\r\n0,%s,V1.00.001,101,V1.00.001,",EQUIP_TYPE_STRING); //备份点号		

	for(i=0; i<g_table_head->di_num; i++)// 遥信
	{
		strcpy(name,"");
		if(g_di_table[i].indexno==0)
		{
			bool bMix=true;
			int m;
			for(m=0; m<g_table_head->di_db_num; m++) // 双点
			{
				if(g_di_table[i].cp==g_di_db_table[m].cp)
				{
					tbl_getdiname(((g_di_db_table[m].no[0]>>8)&0xff),(g_di_db_table[m].no[0]&0xff),name);
					strcat(name,"(双点)");
					bMix=false;
					break;
				}
			}
			if(bMix)  //合并点
			{
				for(m=0; m<g_table_head->dimerge_num; m++)
				{
					if(g_di_table[i].cp==g_di_merge_table[m].cp)
					{
						tbl_getdiname(((g_di_merge_table[m].no[0]>>8)&0xff),(g_di_merge_table[m].no[0]&0xff),name);
						strcat(name,"(合并点)");
						bMix=false;
						break;
					}
				}
			}
			if(bMix) sprintf(name,"备用遥信%d",i+1);

		}
		else
		{
			tbl_getdiname(g_di_table[i].owner,g_di_table[i].indexno,name);
		}
		rt_printf("\r\n1,%04XH,0,3,5,%s",g_di_table[i].cp,name); //备份点号			
	}

	for(i=0; i<g_table_head->ac_num; i++)  // 遥测
	{
		long rate;
		strcpy(name,"");
		if(g_ac_table[i].indexno!=0)
		{
			tbl_getacname(g_ac_table[i].owner,g_ac_table[i].indexno,name);
		}
		else
		{
			sprintf(name,"备用遥测%d",i+1);
		}
		rate=g_ac_table[i].rate;
		if(rate==0)rate=65536;
		rt_printf("\r\n2,%04XH,0,1,20,50,%.2f,0,32768,0,1,%-s",g_ac_table[i].cp,((32768.0*65536)/rate),name); //备份点号
	}

	for(i=0; i<g_table_head->do_num; i++) //遥控
	{
		strcpy(name,"");
		if(g_do_table[i].indexno[0]!=0)
		{
			tbl_getdoname(g_do_table[i].owner,g_do_table[i].indexno[0],name);
		}
		else
		{
			sprintf(name,"备用遥控%d",i+1);
		}
		rt_printf("\r\n5,%04XH,0,0,0,1,%-s",g_do_table[i].cp,name); //备份点号
	}

		rt_printf("\r\n\r\n"); //备份点号


}

/*
 * sunxi 20190625 当 rt_malloc 的参数为0时，返回的地址值是 0x10
 */

int tbl_link_init(void)
{
	int i,num;

	// 遥信
	// 得到级联表个数
	num = 0;
	for(i=0; i<g_table_head->di_num; i++)
	{
		if(g_di_table[i].link_ch)
		{
			num++;
		}
	}
#ifdef FUN_DIMER_LINK
	for(i=0; i<g_di_info_merge_num; i++)
	{
		if(g_di_info_merge_table[i].link_ch)
		{
			num++;
		}
	}	
#endif
#ifdef IECTABLE_NEWDPI_V106

	for(i=0; i<g_table_head->dimerge_num; i++)
	{
		int j;
		for(j=0;j<20;j++)
		{
			if(g_di_merge_table[i].link_ch[j])
			{
				num++;
			}
		}
	}
#endif 
	// 分配内存
	if(num > 0) // sunxi 20190625 当 num为0时返回地址0x10是不正确的。
	{
		g_lt_di = (LINK_TABLE *)rt_malloc(num * sizeof(LINK_TABLE));
		if(g_lt_di == NULL)
		{
			return -11;
		}
		g_lt_di_num = num;

		// 初始化表
		num = 0;
#ifdef FUN_DIMER_LINK	
		for(i=0; i<g_table_head->di_num; i++)
		{	
			if((g_di_table[i].owner == 0) && (g_di_table[i].indexno == 0))	/*该点为双点或者合并点*/
			{
				int no=0;				
				for(no=0;no<g_di_info_merge_num;no++)	/*组合点*/
				{					
					if(g_di_info_merge_table[no].cp != g_di_table[i].cp) continue;

					if(g_di_info_merge_table[no].link_ch)
					{
						g_lt_di[num].cp_s = g_di_info_merge_table[no].link_cp| (g_di_info_merge_table[no].link_ch << 16);
						g_lt_di[num].tbl_index = i;
						g_lt_di[num].owner=g_di_info_merge_table[no].owner;
						g_lt_di[num].indexno=g_di_info_merge_table[no].indexno;
						g_lt_di[num].is_inverse=g_di_info_merge_table[no].is_inverse;
						g_lt_di[num].cp=g_di_info_merge_table[no].cp;
						g_lt_di[num].is_mix=1;				
						num++;
					}																
				}

			}
			else
			{
				if(g_di_table[i].link_ch)
				{
					// TODO:需要排序

					g_lt_di[num].cp_s = g_di_table[i].link_cp| (g_di_table[i].link_ch << 16);
					g_lt_di[num].tbl_index = i;
					g_lt_di[num].owner=g_di_table[i].owner;
					g_lt_di[num].indexno=g_di_table[i].indexno;
					g_lt_di[num].is_inverse=g_di_table[i].is_inverse;
					g_lt_di[num].cp=g_di_table[i].cp;
					g_lt_di[num].is_mix=0;				
					num++;
				}											
			}
						
		}			
#else
		for(i=0; i<g_table_head->di_num; i++)
		{
			if(g_di_table[i].link_ch)
			{
				// TODO:需要排序

				g_lt_di[num].cp_s = g_di_table[i].link_cp| (g_di_table[i].link_ch << 16);
				g_lt_di[num].tbl_index = i;
				g_lt_di[num].owner=g_di_table[i].owner;
				g_lt_di[num].indexno=g_di_table[i].indexno;
				g_lt_di[num].is_inverse=g_di_table[i].is_inverse;
				g_lt_di[num].cp=g_di_table[i].cp;
				g_lt_di[num].is_mix=0;				
				num++;
			}			
		}
#endif
#ifdef IECTABLE_NEWDPI_V106
		for(i=0; i<g_table_head->dimerge_num; i++)
		{
			int j;
			for(j=0;j<20;j++)
			{
				if(g_di_merge_table[i].link_ch[j])
				{
					g_lt_di[num].cp_s = g_di_merge_table[i].link_cp[j]| (g_di_merge_table[i].link_ch[j] << 16);
					g_lt_di[num].owner=(u8)(g_di_merge_table[i].no[j]>>8);
					g_lt_di[num].indexno=(u8)(g_di_merge_table[i].no[j]>>0);
					g_lt_di[num].is_inverse=(u8)(g_di_merge_table[i].is_inv[j]);
					g_lt_di[num].cp=g_di_merge_table[i].cp;
					g_lt_di[num].is_mix=1;
					g_lt_di[num].tbl_index=j;	// 在对应点表中的索引
					num++;
				}
			}
		}
#endif
	}
	else
		g_lt_di_num = 0;

	// 遥控
	// 得到级联表个数
	num = 0;
	for(i=0; i<g_table_head->do_num; i++)
	{
		if(g_do_table[i].link_ch)
		{
			num++;
		}
	}

	// 分配内存
	if(num > 0) // sunxi 20190625 当 num为0时返回地址0x10是不正确的。
	{
		g_lt_do = (LINK_TABLE *)rt_malloc(num * sizeof(LINK_TABLE));
	if(g_lt_do == NULL)
	{
		return -12;
	}
	g_lt_do_num = num;

	// 初始化表
	num = 0;
	for(i=0; i<g_table_head->do_num; i++)
	{
		if(g_do_table[i].link_ch)
		{
			// TODO:需要排序
			g_lt_do[num].cp_s = g_do_table[i].link_cp| (g_do_table[i].link_ch << 16);
			g_lt_do[num].tbl_index = i;
			num++;
			}
		}
	}
	else
		g_lt_do_num = 0;
	
	// 遥测
	// 得到级联表个数
	num = 0;
	for(i=0; i<g_table_head->ac_num; i++)
	{
		if(g_ac_table[i].link_ch)
		{
			num++;
		}
	}

	// 分配内存
	if(num > 0) // sunxi 20190625 当 num为0时返回地址0x10是不正确的。
	{
		g_lt_ac = (LINK_TABLE *)rt_malloc(num * sizeof(LINK_TABLE));
		if(g_lt_ac == NULL)
	{
		return -13;
	}
	g_lt_ac_num = num;

	// 初始化表
	num = 0;
	for(i=0; i<g_table_head->ac_num; i++)
	{
		if(g_ac_table[i].link_ch)
		{
			// TODO:需要排序
			g_lt_ac[num].cp_s = g_ac_table[i].link_cp | (g_ac_table[i].link_ch << 16);
			g_lt_ac[num].tbl_index = i;
			num++;
			}
		}
	}
	else
		g_lt_ac_num = 0;

	// 电度
	// 得到级联表个数
	num = 0;
	for(i=0; i<g_table_head->dd_num; i++)
	{
		if(g_dd_table[i].link_ch)
		{
			num++;
		}
	}

	// 分配内存
	if(num > 0) // sunxi 20190625 当 num为0时返回地址0x10是不正确的。
	{
		g_lt_dd = (LINK_TABLE *)rt_malloc(num * sizeof(LINK_TABLE));
		if(g_lt_dd == NULL)
		{
		return -13;
	}
	g_lt_dd_num = num;

	// 初始化表
	num = 0;
	for(i=0; i<g_table_head->dd_num; i++)
	{
		if(g_dd_table[i].link_ch)
		{
			// TODO:需要排序
			g_lt_dd[num].cp_s = g_dd_table[i].link_cp | (g_dd_table[i].link_ch << 16);
			g_lt_dd[num].tbl_index = i;
			num++;
			}
		}
	}
	else
		g_lt_dd_num = 0;
	
	return 0;
}


int tbl_link_exit(void)
{
	// sunxi 20190627 added
	if(g_lt_dd)
	{
		rt_free(g_lt_dd);
		g_lt_dd = 0;
		g_lt_dd_num = 0;
	}

	if(g_lt_ac)
	{
		rt_free(g_lt_ac);
		g_lt_ac = 0;
		g_lt_ac_num = 0;
	}

	if(g_lt_do)
	{
		rt_free(g_lt_do);
		g_lt_do = 0;
		g_lt_do_num = 0;
	}
	
	if(g_lt_di)
	{
		rt_free(g_lt_di);
		g_lt_di = 0;
		g_lt_di_num = 0;
	}

	return 0;
}


LINK_TABLE *tbl_link_di(u16 ch,u16 cp)
{
	u32 i,cp_s;

	// TODO: 需要优化算法
	cp_s = ((ch)<<16) | cp;
	for(i=0; i<g_lt_di_num; i++)
	{
		if(cp_s == g_lt_di[i].cp_s)
		{
			return &g_lt_di[i];
		}
	}


	return 0; 
}


LINK_TABLE *tbl_link_do(u16 ch,u16 cp)
{
	u32 i,cp_s;

	// TODO: 需要优化算法
	cp_s = ((ch)<<16) | cp;
	for(i=0; i<g_lt_do_num; i++)
	{
		if(cp_s == g_lt_do[i].cp_s)
		{
			return &g_lt_do[i];
		}
	}

	return 0; 
}


LINK_TABLE *tbl_link_ac(u16 ch,u16 cp)
{
	u32 i,cp_s;

	// TODO: 需要优化算法
	cp_s = ((ch)<<16) | cp;
	for(i=0; i<g_lt_ac_num; i++)
	{
		if(cp_s == g_lt_ac[i].cp_s)
		{
			return &g_lt_ac[i];
		}
	}

	return 0; 
}

LINK_TABLE *tbl_link_dd(u16 ch,u16 cp)
{
	u32 i,cp_s;

	// TODO: 需要优化算法
	cp_s = ((ch)<<16) | cp;
	for(i=0; i<g_lt_dd_num; i++)
	{
		if(cp_s == g_lt_dd[i].cp_s)
		{
			return &g_lt_dd[i];
		}
	}

	return 0; 
}



int tbl_link_printf(void)
{
	int i;
	LINK_TABLE* lt;

	rt_printf("点号\t级联通道\t级联点号\t开关\t序号\t合并点 \r\n");
	
	rt_printf("级联遥信点表(num=%d):\r\n",g_lt_di_num);
	for(i=0; i<g_lt_di_num; i++)
	{
		//struct di_table * dt;

		lt = &g_lt_di[i];
		//dt = &g_di_table[lt->tbl_index];
		rt_printf("%04x\t%x\t\t%04x\t\t%02d\t%02d\t%d\r\n",lt->cp,lt->cp_s>>16,lt->cp_s&0xffff,lt->owner,lt->indexno,lt->is_mix);
	}

	rt_printf("级联遥测点表(num=%d):\r\n",g_lt_ac_num);
	for(i=0; i<g_lt_ac_num; i++)
	{
		struct ac_table * dt;

		lt = &g_lt_ac[i];
		dt = &g_ac_table [lt->tbl_index];
		rt_printf("%04x\t%02d\t\t%04x\t\t%02d\t%02d\r\n",dt->cp,lt->cp_s>>16,lt->cp_s&0xffff,dt->owner,dt->indexno);
	}

	rt_printf("级联遥控点表(num=%d):\r\n",g_lt_do_num);
	for(i=0; i<g_lt_do_num; i++)
	{
		struct do_table * dt;

		lt = &g_lt_do[i];
		dt = &g_do_table[lt->tbl_index];
		rt_printf("%04x\t%02d\t\t%04x\t\t%02d\t%02d\r\n",dt->cp,lt->cp_s>>16,lt->cp_s&0xffff,dt->owner,dt->indexno);
	}

	rt_printf("级联电度点表(num=%d):\r\n",g_lt_dd_num);
	for(i=0; i<g_lt_dd_num; i++)
	{
		struct dd_table * dt;

		lt = &g_lt_dd[i];
		dt = &g_dd_table [lt->tbl_index];
		rt_printf("%04x\t%02d\t\t%04x\t\t%02d\t%02d\r\n",dt->cp,lt->cp_s>>16,lt->cp_s&0xffff,dt->owner,dt->indexno);
	}

	
	return 0;
}

 
/*------------------------------ 文件结束 -------------------------------------
*/


