/******************************************************************************
版权所有：	
文件名称：	freq.c
文件版本：	01.01
创建作者:	   sunxi
创建日期：	2008-06-26
功能说明：	DMA定时器驱动程序。目前只使用了DTIM0，作为延时函数的参考定时器用。
			DTIM0的时钟周期为1us。延时函数的最大时间长度为1个小时。
其它说明：  DTIM模块的输入时钟频率DATASHEET上说是 internal bus clock，这个应该
			是fsys/2，但是实际是fsys（即80M）。
修改记录：
 
*/
#include "bsp.h"
#include "rt.h"
#include "head.h"
#include "shm_comm_packet.h"

/*------------------------------- 宏定义 --------------------------------------
*/
/* BSP调试宏定义 */
#if CFG_BSP_DEBUG

#define DTIM_FREQ_DEBUG
#endif


//频率数据结构体
typedef struct SHM_F_T
{
	uint16_t A;
	uint16_t B;
	struct timespec ts;//时间戳
	uint16_t freq[2]; //放大1000倍
	uint16_t crc;
}SHM_F_T;

/*------------------------------ 全局变量 -------------------------------------
*/
float 	g_freqency[CFG_FREQ_NUM];		//最后测量出的频率值。

struct rt_stat g_stat_freq[CFG_FREQ_NUM];
 
/*------------------------------ 外部函数 -------------------------------------
*/
/******************************************************************************
函数名称：	freq_init
函数版本：	01.00
创建作者：	 
创建日期：	2010-05-26
函数说明：	dtim初始化。
		1. 使用dtim0做为延时函数参考定时器；
		2. 使用DTIM2、DTIM3用于两路硬件测频；
参数说明：	无
返回值：  	无
修改记录：	
*/
int freq_init(void)
{

	return 0;	
}


int freq_exit(void)
{

	return 0;
}


static int get_shm_f(uint8_t *out_data)
{
    struct t_shmdata_freq sample;
	int ret = 0;
	int cnt = 0;

	if(out_data == NULL)
		return -1;
		
    while(1)
    {
		ret = shm_packet_read_v2(SHM_ADDR_W_FREQ, sizeof(sample), out_data, sizeof(sample));
		if(ret > 0)	
		{
			break;
		}

		if(++cnt > 3)
			break;

        usleep(30);
    }
    return ret;
}

/******************************************************************************
函数名称：	freq_get
函数版本：	01.01
创建作者:	   sunxi
创建日期：	2008-10-17
函数说明：	得到测量频率的值。
参数说明：	无
返回值：  	返回测量的频率。
修改记录：	
*/
float freq_get(unsigned int index)
{
	u32 e;
	float 	freq = 50.0;
	struct t_shmdata_freq shm_f;
	int ret = 0;
	
#ifdef DTIM_FREQ_DEBUG //added by sunxi: for FUXI
	static int start_stat_flag = 0;

	if(start_stat_flag == 0)
	{
		start_stat_flag++;
		freq_stat_reset();
	}
		
#endif
	
	if(index >= CFG_FREQ_NUM)
	{
		return 0.0;
	}
	if(g_ui_freq[index] == UI_NUM)
	{
		return 0.0;
	}

	// 额定值100V的20%是20V(20%一般是一个测试点),保证测试点频率可用，所以选19V。
	// 20160825:测试发现只要能够测到频率，就基本是准的，所以将门槛降低到5v，满足电子互感器
	// 额定值57.735v的要求。
	e = _Mul_Div_U(sqrt_32fix(g_ui[g_ui_freq[index]].m2[0]), 256, g_ui[g_ui_freq[index]].m2_factor_k);
	if(e < Q16_BASE*5)
	{
		return 0.0;
	}

//==============>
//added by sunxi: for FUXI

	//从共享内存中读取频率到freq
	ret = get_shm_f((uint8_t *)&shm_f);
	// printf("ret=%d, us_updata=%u, us_op=%u, us_op_bk=%u, freq0=%u, freq0=%u, crc=%u\n\n",
	// 	ret, shm_f.us_updata, shm_f.us_op, shm_f.us_op_bk, shm_f.us_freq[0], shm_f.us_freq[1], shm_f.us_crc);

	if(ret < 0)
		return 0.0;

	freq = (float)shm_f.us_freq[index]/1000;

#ifdef DTIM_FREQ_DEBUG
	rt_stat_in(&g_stat_freq[index],rt_round(shm_f.us_freq[index]*Q16_BASE));
#endif
	
	//将频率范围限定在45hz到55hz。
	if(freq>=44.0 && freq <= 56.0)
	{
		g_freqency[index] = freq;
	}
//<=================
	
	return g_freqency[index];
}


int freq_stat_reset(void)
{
	int i;
	for(i=0; i<CFG_FREQ_NUM; i++)
	{
		if(i==0)
		{
			rt_stat_init(&g_stat_freq[0],"freq0");
		}
		else
		{
			rt_stat_init(&g_stat_freq[1],"freq1");
		}
	}

	return 0;
}


int freq_stat_printf(void)
{
	int i;
	
	rt_printf("\r\n[频率测量统计]\r\n");
	for(i=0; i<CFG_FREQ_NUM; i++)
	{
		rt_printf("g_ui_freq[%d]=%d.\r\n",i,g_ui_freq[i]);
		rt_printf("g_freqency[%d]=%f.\r\n",i,g_freqency[i]); // sunxi 20190830 addd
		rt_stat_printf_q16(&g_stat_freq[i]);
	}

	return 0;
}

/*------------------------------ 测试函数 -------------------------------------
*/

#ifdef DTIM_DEBUG

int freq_test(void)
{
	return 0;
}
#endif


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