/******************************************************************************
版权所有：	
文件名称：	dcfactor.c
文件版本：	01.01
创建作者:	   sunxi
创建日期：	2013-05-20
功能说明：	直流系数处理。
其它说明：
修改记录：
*/
/*------------------------------- 头文件 --------------------------------------
*/
#include "head.h"
 
/*------------------------------- 宏定义 --------------------------------------
*/
#define DCFACTOR_FILE_VERSION	0X01010101	//文件版本

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


/*------------------------------ 全局变量 -------------------------------------
*/
float 					g_dc_temp;
struct dc_factor 		g_dcfactor[DC_NUM];
struct dc_factor_save 	g_dcfactor_save[DC_NUM];
u8 g_dcfactor_id[AUTH_ID_LEN];
float dc_adjust[2];
/*------------------------------ 函数声明 -------------------------------------
*/
int dcfactor_init(void);
int dcfactor_readfile(void);
int dcfactor_update(void);


/*------------------------------ 外部函数 -------------------------------------
外部函数供其它实体文件引用，必须仔细检查传入参数的合法性.
*/
/******************************************************************************
函数名称：	dcfactor_init
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	dcfactor初始化。
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int dcfactor_init(void)
{
	int i,ret;
	
	ret = dcfactor_readfile();
	if (ret != 0)
	{
		rt_err_set(ERR_CODE_DCFACTOR,0);
		rt_file_del("/app/data/dcfactor.bin");
		dp_err_n_c_rt("直流系数文件错误: %d\r\n", ret);
		
		for (i=0; i<DC_NUM; i++)
		{
			g_dcfactor_save[i].adjust_set = DC_DEFAULT;
			g_dcfactor_save[i].dc_h = 50;
			g_dcfactor_save[i].dc_l = 10;
		}
		
		g_dc_temp = 40.0;
	}
	_getdcfactorinf();
	dcfactor_update();

	return ret;
}

/******************************************************************************
函数名称：	dcfactor_exit
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	dcfactor退出。
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int dcfactor_exit(void)
{
	return 0;
}

/******************************************************************************
函数名称：	dcfactor_createfile
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	创建直流系数文件
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int dcfactor_createfile(u8 *id, u8 *factor)
{
	unsigned int addr,file_length;
	u16 crc;
	char *p;
	loff_t pos;
	struct file * pfile;
	struct dcfactor_file_head_data	dcfactor_file;
		
	// 写文件头
	memset(&dcfactor_file,0,sizeof(dcfactor_file));
	dcfactor_file.cfh.signature = SIG_DCFACTOR_FILE;
	dcfactor_file.cfh.version = DCFACTOR_FILE_VERSION;
	
	memcpy (&dcfactor_file.auth_id, id, 8);

	// 校正温度更新
#if defined  TMP_CHIP_AHT20
	dcfactor_file.temp = aht20_get_temp();
#endif

	dcfactor_file.addr = FILE_ADDR_ALGIN(sizeof(dcfactor_file));
	dcfactor_file.num = DC_NUM;

	// 得到文件长度
	addr = dcfactor_file.addr + dcfactor_file.num * sizeof(struct dc_factor_save);
	file_length = addr;

	// 分配并初始化空间
	p = rt_malloc(file_length + 2); 
	if(!p)
	{
		return -1;
	}
	memset(p, 0, file_length + 2);
	
	// 写入文件头
	memcpy(p, (char *)&dcfactor_file, sizeof(dcfactor_file));
	
	// 写直流系数
	memcpy(p+dcfactor_file.addr, factor, sizeof(struct dc_factor_save)*2);

	// 计算CRC
	crc = CrcStr(p, file_length);
	memcpy(p+file_length, &crc, 2);

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

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

	memcpy(g_dcfactor_id, id, 8);
	memcpy(g_dcfactor_save, factor, sizeof(g_dcfactor_save));
	dcfactor_update();
	g_dc_temp = dcfactor_file.temp;

	//清除直流告警灯
	rt_err_clr(ERR_CODE_DCFACTOR,0);
	
	return 0;
}

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

	struct dcfactor_file_head_data *brh;
	
	// 创建并打开文件
	pfile = rt_file_open("/app/data/dcfactor.bin",O_RDWR,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 dcfactor_file_head_data*)buf;
	if(brh->cfh.signature != SIG_DCFACTOR_FILE)
	{
		rt_free(buf);
		return -5;
	}
	
//noted by sunxi: 20220413 暂进屏蔽
#ifndef CPU_FUXI
	// 检查FLASH唯一ID号
	memcpy (&g_dcfactor_id, &brh->auth_id, 8);
	if (memcmp (&g_dcfactor_id, g_auth_id, 8) != 0)
	{
		rt_free(buf);
		return -6; 
	}	
#endif

	// 检查文件长度
	len2 = FILE_ADDR_ALGIN(sizeof(*brh)) + brh->num*sizeof(struct dc_factor_save)+ 2;
	if(len != len2)
	{
		rt_printf("dcfactor_readfile:len=%d,len2=%d.\r\n",len,len2);
		rt_free(buf);
		return -7; 	
	}

	//取出文件中存储内容
	g_dc_temp = brh->temp;
	memcpy (&g_dcfactor_save, buf+brh->addr, sizeof(struct dc_factor_save)*2);

	rt_free(buf);
	return 0;
}

/******************************************************************************
函数名称：	dcfactor_update
函数版本：	01.01
创建作者：	xxxxxx
创建日期：	2015-10-23
函数说明：	更新程序实际的直流系数
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int dcfactor_update(void)
{
	int i;

	// 直流量校正系数
	for (i=0; i<DC_NUM; i++)
	{
		if (g_dcfactor_save[i].dc_h-g_dcfactor_save[i].dc_l == 0)
		{
			g_dcfactor[i].f_dc = 1;
		}
		else
		{
			g_dcfactor[i].f_dc = (dc_adjust[1] - dc_adjust[0])/(g_dcfactor_save[i].dc_h-g_dcfactor_save[i].dc_l);
		}
		g_dcfactor[i].f_dcL = g_dcfactor_save[i].dc_l;
	}
	return 0;
}


int dcfactor_restore_default(void)
{
	int i;
	
struct dc_factor_save factor[2];
	
	for(i=0; i<DC_NUM; i++)
	{	
		factor[i].dc_l = dc_adjust[0];
		factor[i].dc_h = dc_adjust[1];
		factor[i].adjust_set = DC_DEFAULT;
	}

	return dcfactor_createfile(g_auth_id, (u8 *)&factor);
}


void _getdcfactorinf(void)
{
	u32 i,file_length;
	struct file * pfile;
	u8 *filebuf;
	//u8	filestr[128],*pstr,strlenth;
	loff_t pos;
	
	// 打开文件
	pfile = rt_file_open("/app/data/pcolcfg.ini",O_RDONLY ,0);
	if(IS_ERR(pfile))
	{
		dp_err_n_c_rt("error! 无法打开 pcolcfg.ini\r\n");
		goto dc_err;
	}
	// 得到文件长度
	file_length = rt_file_getfile_size(pfile);
	if(file_length <= 0)
	{
		rt_file_close(pfile,0);
		goto dc_err;	
	}

	if(file_length == 0)
	{
		rt_file_close(pfile,0);
		goto dc_err;	
	}

	// 分配内存
	filebuf = rt_malloc(file_length);
	if((filebuf) == NULL)
	{
		rt_file_close(pfile,0);
		goto dc_err;	
	}
	pos = 0;
	if(rt_file_read(pfile,filebuf,file_length,&pos) != file_length)
	{
		rt_file_close(pfile,0);
		rt_free(filebuf);
		goto dc_err;	
	}
	for(i = 0; i < file_length; i++)
	{
		if(strncmp(&filebuf[i],"DC_AJUST_0", 10) == 0) 
		{
			dc_adjust[0] = getstrval(&filebuf[i]);
		}	
		else if(strncmp(&filebuf[i],"DC_AJUST_1", 10) == 0) 
		{
			dc_adjust[1] = getstrval(&filebuf[i]);
			break;
		}
	}
	if(i >= file_length)
	{
		dc_adjust[0] = DC_AJUST_0;
		dc_adjust[1] = DC_AJUST_1;		
	}
	rt_printf("dc_adjust[0] = %f\r\n", dc_adjust[0]);
	rt_printf("dc_adjust[1] = %f\r\n", dc_adjust[1]);	
	rt_file_close(pfile,0); // 关闭文件
	rt_free(filebuf);			// 释放内存
	return;
dc_err:
	dc_adjust[0] = DC_AJUST_0;
	dc_adjust[1] = DC_AJUST_1;
	rt_printf("dc_adjust[0] = %f\r\n", dc_adjust[0]);
	rt_printf("dc_adjust[1] = %f\r\n", dc_adjust[1]);	
}


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


/*------------------------------ 测试函数 -------------------------------------
一个实体文件必须带一个本模块的测试函数来进行单元测试，如果的确不方便在本模块中
进行单元测试，必须在此注明实际的测试位置（例如在哪个实体文件中使用哪个测试函数）.
*/
int dcfactor_printf(void)
{
	int i;
	
	rt_printf("直流校正系数:\r\n");
	rt_printf("校正温度:%f.\r\n",g_dc_temp);
	rt_printf("%d,\t存储标志:%d,\tdc_h=%9f,\tdc_l=%9f \r\n",
	0,
	g_dcfactor_save[0].adjust_set,
	g_dcfactor_save[0].dc_h,
	g_dcfactor_save[0].dc_l);
	
	rt_printf("%d,\t存储标志:%d,\tdc_h=%9f,\tdc_l=%9f \r\n",
	1,
	g_dcfactor_save[1].adjust_set,
	g_dcfactor_save[1].dc_h,
	g_dcfactor_save[1].dc_l);
	rt_printf("存储ID号:0x");
	for (i=0; i<8; i++)
	{
		rt_printf("%02x ", g_dcfactor_id[i]);
	}
	rt_printf("\r\n实际ID号:0x");
	for (i=0; i<8; i++)
	{
		rt_printf("%02x ", g_auth_id[i]);
	}	
	rt_printf("\r\n");
	return 0;
}

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

