/******************************************************************************
版权所有：	
文件名称：	factor.c
文件版本：	01.01
创建作者:	   sunxi
创建日期：	2013-05-20
功能说明：	通道参数处理。
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include "head.h"
 
/*------------------------------- 宏定义 --------------------------------------
*/
#define FACTOR_P_BASE (-360.0/32/8)

//CT PT标度,1V或1A对应的码值
// = (二次有效值/一次有效值)*(AD码值范围/电压范围(V))*1.4142
// = (7.07/一次有效值)*(65536/20)*1.4142
// = (7.07*65536/20*1.4142)/ 一次有效值.
#define SCALE_PT_BIG		(32768.0)					// 二次有效值为7.07V或3.53V，需对应改变ADC的输入范围
#define SCALE_CT_BIG		(32768.0)					// 二次有效值为7.07V或3.53V，需对应改变ADC的输入范围

// 使用初级电阻标识
#define SCALE_PT_102K		(1.650*32768/5.0*1.4142)	// DTU FTU使用电阻配置100V 
#define SCALE_PT_120K		(1.032*32768/2.5*1.4142)	//153K
#define SCALE_PT_150K		(1.0348*32768/2.5*1.4142)	//  开普测试，测量范围264 增加了电阻
#define SCALE_PT_172K		(0.916*32768/2.5*1.4142)	// 加264V相电压二次用万用表测有效值为0.916v
// #define SCALE_PT_204K		(0.513*32768/2.5*1.4142)	// 次级电阻200k  最终版本
// DTUv5与DTUv4同样硬件，系数一样
#define SCALE_PT_204K		(0.1105*32768/2.5*1.4142)	// 加264V相电压二次用万用表测有效值为0.063v		初级241KΩ次级100Ω
#define SCALE_PT_FUXI       (0.1090 * 32768 / 5.0 * 1.4142)

// 使用次级电阻标识
#define SCALE_CT_100A_51	(2.526*32768/5.0*1.4142)	// 次级电阻51欧,,加5A相电流二次用万用表测有效值为0.127V
#define SCALE_CT_10A_51	    (0.254*32768/2.5*1.4142)	// 次级电阻51欧,加10A相电流二次用万用表测有效值为0.254V
#define SCALE_CT_10A_120	(1.27*32768/2.5*1.4142)	// 次级电阻249欧,加10A相电流二次用万用表测有效值为0.643V  // 零序穿心5倍 最大量程20A
#define SCALE_CT_10A_249	(1.265*32768/5.0*1.4142)	//  1ACT 量程20A
#define SCALE_CT_10A_604	(3.235*32768/5.0*1.4142)	// 次级电阻604欧,加10A相电流二次用万用表测有效值为3.235V
#define SCALE_CT_FUXI       (3.069 * 32768 / 5.0 * 1.4142)

#define SCALE_EVT			(32768.0)
#define SCALE_ECT			(32768.0)

#define SCALE_PT_DEFAULT	SCALE_PT_FUXI
#define SCALE_CT_DEFAULT	SCALE_CT_FUXI

/*------------------------------ 类型结构 -------------------------------------
*/


/*------------------------------ 全局变量 -------------------------------------
*/
// 比例系数计算方法请参考<电子互感器比例系数计算方法.xlsx>
static const float g_e_k[EQU_SCALE_NUM] = 
{
	SCALE_PT_BIG/(220*1.2),
	SCALE_PT_DEFAULT/(220*1.2),
	SCALE_EVT/(108.7856586),	// EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100;
	SCALE_EVT/(31.31),	// EQU_SCALE_EVT 最大测到30V
#if 1
	SCALE_CT_BIG/54.752,
#else
	SCALE_CT_BIG/100,
#endif

	SCALE_CT_DEFAULT/100 ,
	SCALE_ECT/(10.60660172),	// EQU_SCALE_ECT_1V_1A,	1V=1A
	SCALE_ECT/(11.73797257),	// EQU_SCALE_ECT_0V2_1A,0.2V=1A.
	SCALE_CT_10A_51/10 ,
	SCALE_PT_102K/(220*1.2),
	SCALE_PT_120K/(220*1.2),
	SCALE_PT_172K/(220*1.2),
	SCALE_PT_204K/(220*1.2),
	SCALE_CT_10A_604/10 ,
	SCALE_CT_10A_120/10 ,
	SCALE_CT_10A_249/10 ,
};

//一次/二次变比
static const float g_e_ps[EQU_SCALE_NUM] = 
{
	10000.0/220.0,
	10000.0/100.0,
	10000.0/100.0,	// EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100;
	5773.502692/(100.0/3),	// EQU_SCALE_EVT_6V50_100V,
	600.0/5.0,
	600.0/5.0,
	600.0/1.0,	// EQU_SCALE_ECT_1V_1A,	1V=1A
	20.0/1.0,	// EQU_SCALE_ECT_0V2_1A,0.2V=1A.
	600.0/1.0,	
	10000.0/100.0,
	10000.0/100.0,
	10000.0/100.0,
	10000.0/100.0,
	10000.0/100.0,
	10000.0/100.0,
	10000.0/100.0,
};

// 电子互感器和电磁互感器二次值换算的比值
const float g_e_k_ECVT[EQU_SCALE_NUM] = 
{
	1.0,
	1.0,
	0.0325,	// EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100;
	0.065,	// EQU_SCALE_EVT_6V50_100V,
	1.0,
	1.0,
	1.0,	// EQU_SCALE_ECT_1V_1A,	1V=1A
	0.2,	// EQU_SCALE_ECT_0V2_1A,0.2V=1A.
	1.0,
	1.0,
	1.0,
	1.0,
	1.0,
	1.0,
	1.0,
	1.0,
};


struct ac_slot_factor g_ac_factor[EQU_SLOT_AC_NUM];

u32 g_factor_version = ACFACTOR_FILE_VERSION;
u16 g_base_v,g_base_i;

/*------------------------------ 函数声明 -------------------------------------
*/
int factor_read_all(void);

int factor_printf_temp(void);

/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/
int factor_init(void)
{
	int slot,ret;

	// 取默认值
	g_factor_version = ACFACTOR_FILE_VERSION;
	for(slot=0; slot<EQU_SLOT_AC_NUM; slot++)
	{
		factor_get_default(&g_ac_factor[slot]);
	}

	// 检查装置配置
	if(equ_config_null())
	{
		return -1;
	}

	// 从文件系统读取系数
	ret = factor_read_all();
	if(ret != 0)
	{
		rt_err_set(ERR_CODE_FACTOR,0);
		dp_err_n_c("交流系数文件错误: (ret=%d)\r\n", ret);

		return -2;
	}
	
	return 0;
}


int factor_exit(void)
{
	return 0;
}
int factor_read(u32 slot,struct ac_slot_factor *asf)
{
	// 检查参数
	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM || asf == NULL)
	{
		return -1;
	}
	
	memcpy ((u8*)asf, &g_ac_factor[slot], sizeof(struct ac_slot_factor));

	return 0;
}



/******************************************************************************
函数名称：	factor_write
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	创建交流系数文件
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int factor_write(u32 slot,struct ac_slot_factor *asf)
{
	// 检查参数
	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM || asf == NULL)
	{
		return -1;
	}
	
	memcpy (&g_ac_factor[slot],(u8*)asf,  sizeof(struct ac_slot_factor));

	return 0;
}

/******************************************************************************
函数名称：	factor_read
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	读取交流系数文件
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int factor_read_all(void)
{
	int len;
	u16 crc;
	u8 *buf;
	off_t pos;
	struct file * pfile;
	//int file_size;

	struct acfactor_file_head_data *brh;

	
	// 创建并打开文件
	pfile = (struct file *)rt_file_open("/app/data/acfactor.bin",O_RDWR,0);
	if(IS_ERR(pfile))
	{
		return -2;
	}

	// 得到文件长度
	len = rt_file_getfile_size(pfile);
	if(len <= 0)
	{
		rt_file_close(pfile, 0);
		return -21;
	}

	// 分配内存
	buf = (u8 *)rt_malloc(len);
	if((buf) == NULL)
	{
		rt_file_close(pfile,0);
		return -3; 	
	}

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

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

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

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

#if 0
	// 检查文件版本
	if(brh->cfh.version != ACFACTOR_FILE_VERSION)
	{
		rt_free(buf);
		return -66;
	}
#endif	

//noted by sunxi: 20220413 暂进屏蔽
#if 0
	// 检查FLASH唯一ID号
	if (memcmp (brh->auth_id, g_auth_id, 8) != 0)
	{
		rt_free(buf);
		return -7; 
	}	
#endif

	// 检查板卡数量
	if(brh->num != EQU_SLOT_AC_NUM)
	{
		rt_free(buf);
		return -77; 
	}
	
	// 检查文件长度
	if(len < (int)(sizeof(*brh) + brh->num*sizeof(struct ac_slot_factor)+ 2))
	{
		rt_free(buf);
		return -8; 	
	}

	//取出文件中存储内容
	g_factor_version = brh->cfh.version;
	g_base_v = brh->base_v;
	g_base_i = brh->base_i;
	memcpy ((u8*)g_ac_factor, buf+brh->addr, EQU_SLOT_AC_NUM*sizeof(struct ac_slot_factor));

	rt_free(buf);
	return 0;
}


int factor_write_all(u16 base_v,u16 base_i)
{
	unsigned int addr,file_length;
	u16 crc;
	char *p;
	off_t pos;
	int pfile;
	struct acfactor_file_head_data	acfactor_file;
		
	// 写文件头
	memset(&acfactor_file,0,sizeof(acfactor_file));
	acfactor_file.cfh.signature = SIG_ACFACTOR_FILE;
	acfactor_file.cfh.version = ACFACTOR_FILE_VERSION;
	
	memcpy (&acfactor_file.auth_id, g_auth_id, 8);

	acfactor_file.base_v = base_v ? base_v : g_base_v;
	acfactor_file.base_i = base_i ? base_i : g_base_i;
	g_base_v = acfactor_file.base_v;
	g_base_i = acfactor_file.base_i;
	
	acfactor_file.addr = FILE_ADDR_ALGIN(sizeof(acfactor_file));
	acfactor_file.num = EQU_SLOT_AC_NUM;

	// 得到文件长度
	addr = acfactor_file.addr + acfactor_file.num * sizeof(struct ac_slot_factor);
	file_length = FILE_ADDR_ALGIN(addr);

	// 分配并初始化空间
	p = (u8 *)rt_malloc(file_length + 2);
	if(!p)
	{
		rt_err_set(ERR_CODE_FACTOR,0);
		return -2;
	}
	memset(p, 0, file_length + 2);
	
	// 写入文件头
	memcpy(p, (char *)&acfactor_file, sizeof(acfactor_file));
	
	// 写系数
	memcpy(p+acfactor_file.addr, g_ac_factor, EQU_SLOT_AC_NUM * sizeof(struct ac_slot_factor));

	// 计算CRC
	crc = CrcStr(p, file_length);
	memcpy(p+file_length, &crc, 2);
	//swap16(p+file_length);//added by sunxi: 大小端问题 ----- 维护工具好像没有处理crc的大小端

	// 创建数据文件
	pfile = rt_file_open("/app/data/acfactor.bin",O_CREAT|O_RDWR|O_TRUNC,0);
	if(IS_ERR(pfile))
	{
		rt_err_set(ERR_CODE_FACTOR,0);
		rt_free(p);
		return -3;
	}
	
	pos = 0;
	rt_file_write(pfile, p, file_length+2, &pos);

	rt_file_close(pfile,0);
	
	rt_free(p);

	system("sync");//noted by sunxi: 把写好的文件，写到系统中去，不然，断电重启，有机会掉失

	//清除交流告警灯
	rt_err_clr(ERR_CODE_FACTOR,0);
	
	return 0;
}

int factor_write_board(u32 slot,struct ac_slot_factor *asf)
{
	int ret ;

	ret = factor_write(slot,asf);
	if(ret != 0)
	{
		rt_err_set(ERR_CODE_FACTOR,slot);
		rt_printf("factor_write_board:slot=%lu,ret=%d.\r\n",slot,ret);
		return -1;
	}

	g_base_v = 0;
	g_base_i = 0;
	ret = factor_write_all(0,0);

	return ret;
}


int factor_get_default(struct ac_slot_factor *asf)
{
	int i;
	
	if(asf == NULL)
	{
		return -1;
	}

	for(i=0; i<EQU_SLOT_AC_CHN; i++)
	{
		asf->factor_e_c[i] = 1.0;
		asf->factor_p_c[i] = 0.0;
	#ifdef PROTECT_AC_ADJUST
		asf->factor_p_e_c[i] = 1.0;
	#endif	
		asf->pq_factor[i][0] = 0.0;
		asf->pq_factor[i][1] = 0.0;
	}

	asf->temp = 35.0;

	return 0;
}

int factor_restore_default(void)
{
	int slot,ret ;

	// 取默认值
	g_factor_version = ACFACTOR_FILE_VERSION;
	for(slot=0; slot<EQU_SLOT_AC_NUM; slot++)
	{
		factor_get_default(&g_ac_factor[slot]);
	}

	// 重新初始化开关
	sw_init();
	
	// 保存
	g_base_v = 0;
	g_base_i = 0;
	ret = factor_write_all(0,0);

	rt_printf("factor_restore_default(ret=%d).\r\n",ret);
	
	return ret;
}
 

int factor_e_c_get(u32 slot,u32 index,float *f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	if(f == NULL)
	{
		return -2;
	}

	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -3;
	}

	*f = g_ac_factor[slot].factor_e_c[index];
	
	return 0;
}

int factor_e_c_set(u32 slot,u32 index,float f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -2;
	}

	g_ac_factor[slot].factor_e_c[index] = f;

	return 0;
}

int  factor_p_c_get(u32 slot,u32 index,float *f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	if(f == NULL)
	{
		return -2;
	}

	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -3;
	}

	*f = g_ac_factor[slot].factor_p_c[index];

	return 0;
}


int factor_p_c_set(u32 slot,u32 index,float f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -2;
	}

	g_ac_factor[slot].factor_p_c[index] = f;

	return 0;
}

#ifdef PROTECT_AC_ADJUST
int factor_p_e_c_get(u32 slot,u32 index,float *f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	if(f == NULL)
	{
		return -2;
	}

	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -3;
	}

	*f = g_ac_factor[slot].factor_p_e_c[index];
	
	return 0;
}

int factor_p_e_c_set(u32 slot,u32 index,float f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -2;
	}

	g_ac_factor[slot].factor_p_e_c[index] = f;

	return 0;
}
#endif

int factor_pq_get(u32 slot,u32 index,float *f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	if(f == NULL)
	{
		return -2;
	}

	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -3;
	}

	*f++ = g_ac_factor[slot].pq_factor[index][0];
	*f   = g_ac_factor[slot].pq_factor[index][1];

	return 0;
}


int factor_pq_set(u32 slot,u32 index,float *f)
{
	// 检查参数
	if(index >=(u32)equ_get_ac_num(slot))
	{
		return -1;
	}
	
	if(f == NULL)
	{
		return -2;
	}

	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -3;
	}
	
	g_ac_factor[slot].pq_factor[index][0] = *f++;
	g_ac_factor[slot].pq_factor[index][1] = *f;

	return 0;
}


float factor_e_k(u32 index)
{
	if(index >= EQU_SCALE_NUM)
	{
		return -1;
	}

	return g_e_k[index];
}

float factor_e_ps(u32 index)
{
	if(index >= EQU_SCALE_NUM)
	{
		return -1;
	}

	return g_e_ps[index];
}

float factor_p_k(u32 index)
{
	if(index >= CFG_ADC_CHANNEL)
	{
		return 0;
	}
    // 保持旧版本的兼容性
    {
        u32 us;

        if (g_factor_version != ACFACTOR_FILE_VERSION)
        {
            return (index / 8) * FACTOR_P_BASE;
        }

        // 1倍过采样延时1us
        us = (index % 16) / 2 * CFG_ADC_OS_NUM;
        return -g_freq * us / 1000000.0 * 360;
    }
    return 0;
}


int factor_temp_get(int slot,float *temp)
{
	// 检查参数
	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -1;
	}


	*temp  = g_ac_factor[slot].temp;

	return 0;
}


int factor_temp_set(int slot,float temp)
{
	// 检查参数
	slot -= g_ac_slot_begin;
	if(slot >= EQU_SLOT_AC_NUM)
	{
		return -1;
	}


	g_ac_factor[slot].temp = temp;

	return 0;
}

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


/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/
int factor_printf(void)
{
	int slot,j;
	float f;
	
	rt_printf("校正系数:\r\n");
	rt_printf("版本:0x%08lx.\r\n",g_factor_version);
	rt_printf("最后校准基准值:电压=%d,电流=%d.\r\n",g_base_v,g_base_i);
	for(slot=0; slot<EQU_SLOT_AC_NUM; slot++)
	{
		rt_printf("序号:%02d(temp=%f).\r\n",slot,g_ac_factor[slot].temp);
		for(j=0;j<EQU_SLOT_AC_CHN;j++)
		{
			rt_printf("%02d:\tec=% 9f,\tpc=% 9f,\tpq1=% 9f,\tpq2=% 9f.\r\n",j,
			g_ac_factor[slot].factor_e_c[j],
			g_ac_factor[slot].factor_p_c[j],
			g_ac_factor[slot].pq_factor[j][0],
			g_ac_factor[slot].pq_factor[j][1]);
		}
	}
	for(j=0;j<(int)(sizeof(g_e_k)/sizeof(g_e_k[0])); j++)
	{
		rt_printf("g_e_k[%d]:%f.\r\n",j,g_e_k[j]);
	}

	for(j=0;j<16;j++)
	{
		f = factor_p_k(j);
		rt_printf("factor_p_k(%02d):%f.\r\n",j,f);
	}

	return 0;
}
 

//========================== 本文件结束 =============================

