/******************************************************************************
版权所有：	
文件名称：	pit.c
文件版本：	01.01
创建作者:	sunxi
创建日期：	2008-06-25
功能说明：	可编程中断定时器程序。
			
其它说明：	
修改记录：
*/

/*------------------------------- 头文件 --------------------------------------
*/
#include "bsp.h"
#include "rt.h"
#include "head.h"



/*------------------------------- 宏定义 --------------------------------------
*/


/*------------------------------ 全局变量 -------------------------------------
*/
unsigned int g_count_156us;

FN_PIT_CALLBACK g_pit_callback_5ms;
FN_PIT_CALLBACK g_pit_callback_156us;

struct rt_stat g_stat_156us;
struct rt_stat g_stat_5ms;
extern struct rt_stat g_stat_periodus_5ms;

void pit_156us_isr(void);
void pit_5ms_isr(void);
//void pit_250us_isr(void); // sunxi 20190425 added

int pit_500us_isr(int irq, void *data);
/*------------------------------ 外部函数 -------------------------------------
*/


/******************************************************************************
函数名称：	pit_init
函数版本：	01.01
创建作者:	sunxi
创建日期：	2008-06-25
函数说明：	pit初始化。目前使用PIT0产生1ms中断。
参数说明：	无
返回值：  	无
修改记录：	
*/
int pit_init(void)
{
	pit_stat_reset();
	return 0;	
}

int pit_exit(void)
{

	rt_free_irq(CFG_PIT_VECTOR_BEGIN+CFG_PIT_5MS); 	// 释放5ms中断
	rt_free_irq(CFG_PIT_VECTOR_BEGIN+CFG_PIT_SAMPLE);	// 释放156us中断

	return 0;
}

/******************************************************************************
函数名称：	pit_regester_callback
函数版本：	01.01
创建作者:	sunxi
创建日期：	2011-04-22
函数说明：	登记PIT的定时回调函数。
参数说明：	
	period_us:	定时周期，以us为单位。
	fn：			回调函数。
返回值：  	成功返回0，失败返回负数。
修改记录：	
*/
int pit_regester_callback(int period_us,FN_PIT_CALLBACK fn)
{
	switch(period_us)
	{
	case 5000:
		g_pit_callback_5ms = fn;
		break;
	case 156:
		g_pit_callback_156us = fn;
		break;
	default:
		return -1;
	}
	
	return 0;
}


/******************************************************************************
函数名称：	pit_156us_period_set
函数版本：	01.01
创建作者:	sunxi
创建日期：	2012-12-05
函数说明：	通过测得的线路频率，修改采样周期。
参数说明：	
	hz:		通过测频电路测得的线路频率。Q16定点数。
返回值：  	成功返回0，失败返回负数。
修改记录：	
*/
int pit_156us_period_set(float hz)
{
	unsigned short pmr;

	hz *= CFG_ADC_DOTS_PER_PERIOD*4;// 128点采样

	// 根据公式计算pmr。
	pmr = (unsigned short)rt_round((CFG_CPU_CLK/2)/hz);
	pmr -= 2;

	//设置定时周期。
//	MCF_PIT3_PMR = pmr;

	//rt_printf("pit_156us_period:hz=%s,pmr=0x%04x\r\n",q16_to_str(hz/128),pmr);
	
	return 0; 
}

/******************************************************************************
函数名称：	pit_5ms_isr
函数版本：	01.01
创建作者:	sunxi
创建日期：	2008-06-25
函数说明：	pit0中断服务程序。
参数说明：	无
返回值：  	无
修改记录：	
*/
void pit_5ms_isr(void)
{
	// 统计中断延时
//	rt_stat_in(&g_stat_5ms,(uint32_t)(PIT_PERIOD_5MS - MCF_PIT2_PCNTR));

	// 先清除中断
//	MCF_PIT2_PCSR |= MCF_PIT_PCSR_PIF;	
 
	//5ms主回调函数
    if(g_pit_callback_5ms)
    {
    	g_pit_callback_5ms(0);
    }

	//软件狗喂狗
    watchdog_feed_protect();
}


/******************************************************************************
函数名称：	pit_156us_isr
函数版本：	01.01
创建作者:	sunxi
创建日期：	2011-04-22
函数说明：	pit1中断服务程序。
参数说明：	无
返回值：  	无
修改记录：	
*/
//extern struct rt_irq_node g_rt_irq_list[RT_IRQS_NUM];
void dido_soe_gen(void);
void pit_156us_isr(void)
{
#if 0
	int mod;
	uint32_t count;
	uint32_t us0;

	count = (uint32_t)(MCF_PIT3_PMR - MCF_PIT3_PCNTR);
	rt_stat_in(&g_stat_156us,count);

	us0 = ustimer_get_origin();
 
	// 先清除中断。
	MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF;

	//根据g_count_156us统一计算mod和is625us，保证两者的同步。
	mod = (int)(g_count_156us &0x03);
//	is625us = (mod == 0x03) ? 1:0;
	
	//调用ADC中断处理函数
	adc_isr(mod);

	// SOE发生器
	dido_soe_gen();
	
	// 遥信扫描
	dido_di_poll();

	//回调156us应用处理函数
	if (g_pit_callback_156us != NULL)
	{
		g_pit_callback_156us(mod);
	}
	
	//计数器加一。
	g_count_156us++;

	// 喂ADC看门狗
	watchdog_feed_adc();

	// 由于针对采样中断的入口进行了优化，所以将时间统计放在这儿。
	rt_stat_in(&g_rt_irq_list[CFG_PIT_VECTOR_BEGIN+3].stat,ustimer_get_duration(us0));
#endif
}


int pit_stat_reset(void)
{
	rt_stat_init(&g_stat_156us,"pit_156us_isr(8ns)");
	rt_stat_init(&g_stat_5ms,"pit_5ms_isr(128ns)");
	rt_stat_init(&g_stat_periodus_5ms, "pit_5ms_priod(1us)");

	return 0;
}


int pit_stat_printf(void)
{
	rt_printf("\r\n[实时中断延时统计(单位:见各行)]\r\n");
	
	rt_stat_printf(&g_stat_156us);
	rt_stat_printf(&g_stat_5ms);
	rt_stat_printf(&g_stat_periodus_5ms);

	return 0;
}


int pit_500us_isr(int irq, void *data)
{
	// 清除中断标志
	//MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;

	//goose_timer_handle();

	return 0;
}


/*------------------------------ 测试函数 -------------------------------------
*/
//#ifdef CFG_BSP_DEBUG
#if 0

#include "ustimer.h"

int pit_test(void)
{
	uint32_t t,t0;
	
	t=0;
	t0 = ustimer_get_origin();
	sti(0);		
	while(1)
	{
		rt_printf("pit(t=%04d):5ms:%06d,156us:%08d,[156us-t*6400:%d],[5ms-t*200:%d]!\r\n",
				t,
				g_count_5ms,
				g_count_156us,
				g_count_156us -t*6400,
				g_count_5ms -t*200);
		
		watchdog_feed_software_5s();
		
		t++;
		ustimer_delay_origin(t0,t*USTIMER_SEC);
		
	}
}

#endif


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