/******************************************************************************
版权所有：	
文件名称：	rt_gps.c
文件版本：	01.01
创建作者:	   sunxi
创建日期：	2008-06-04
功能说明：	GPS时钟模块驱动程序。
其它说明：	1. GPS卫星同步时钟只保证整秒时PR上升沿的精度（一般1us之内），
		   其它bit的上升沿精度并不保证。
		2. GPS接收模块只给出秒脉冲和串口数据。
		3. 使用B码对时的时候，B码给的数据中可能包含闰秒（负闰秒：58->0;
		   正闰秒：60->0），所以秒的有效数据范围为0～60。但是系统中其它
		   计时模块没有闰秒的概念，单独在B码模块使用闰秒有可能造成整个计时
		   系统的混乱，所以最终决定将秒的有效数据范围还是限制在0～59，这样
		   当正闰秒出现时，系统时间将是：58->59->0->0-1。初步估计，这种影响
		   在可接受的范围之内。
		4. 目前在冷火Linux平台上对时误差<8US.(2010-11-23)
修改记录：
*/

/*------------------------------- 头文件 --------------------------------------
*/
#include "bspconfig.h"
#include "my_rtc.h"
#include "rt.h"
#include "bsp_ccu.h"
#include "bsp_ustimer.h"
#include "rt_printf.h"
#include "rt_types.h"
#include <sys/mman.h>

#include "gps.h"
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <pthread.h>
#include <sched.h>


/*------------------------------- 宏定义 --------------------------------------
*/
#if CFG_BSP_DEBUG

#define _DEBUG_GPS

#endif

#define DTIM_CLOCK_PER_US	(CFG_CPU_CLK/2/1000000)

#define GPS_SIGAL_DIFF		1	//GPS信号宽度误差

#define GPS_IRIG_CODE_0		0
#define GPS_IRIG_CODE_1		1
#define GPS_IRIG_CODE_P		2

/*------------------------------ 全局变量 -------------------------------------
*/
extern int g_clock_mode;
struct timespec g_sys_time;
static struct rtc_time_t tmp_sys_time;

//毫秒中断的参考值
unsigned int g_1s_refence;

//输入信号是否合法，合法为1，不合法为0
int g_signal_valid;

//GPS对时使用的保活计数值
unsigned int g_keep_alive_gps;

//处理B码的全局变量
unsigned int g_irig_old_value;
unsigned int g_irig_old_interval;
unsigned int g_irig_code_index;
unsigned char g_irig_code[100];


int g_gps_fd = -1;
unsigned g_gps_mapped_size;
void *g_gps_map_base, *g_gps_virt_addr; 

static void* gpio_base = NULL;

/*------------------------------ 函数声明 -------------------------------------
*/
int _gps_irig_decode(unsigned char *code,struct rtc_time_t * p_tm );
void _ms_update_time(void);
void _gps_capture_isr(void);
void _gps_1s_isr(void);
void gps_isr(void);

/*------------------------------ 外部函数 -------------------------------------
*/
/******************************************************************************
函数名称：	gps_init
函数版本：	01.01
创建作者:	ocean
创建日期：	2025-11-21
函数说明：	gps初始化。
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int gps_init(void)
{
	struct timespec ts;
	struct rtc_time_t ct;
	void *temp_ccu_base, *temp_virt_l_base, *temp_virt_h_base, *temp_virt_ctl_base, *temp_virt_irq_base;
    unsigned long read_result;
    off_t target;
	unsigned page_size, offset_in_page;
    unsigned width = 8 * sizeof(int);
    target = TIMER_BASE;
    // 获取页面大小
    g_gps_mapped_size = page_size = sysconf(_SC_PAGESIZE);
    offset_in_page = (unsigned)target & (page_size - 1);
    if (offset_in_page + width > page_size) {
		/* This access spans pages.
		 * Must map two pages to make it possible: */
		g_gps_mapped_size *= 2;
	}
    
    g_gps_fd = open("/dev/mem",  O_RDWR | O_SYNC);
    if (g_gps_fd < 0)  
    {
        printf("open(/dev/mem) failed.\n");    
        return -1;
    }
    fflush(stdout);

    g_gps_map_base = mmap (NULL, g_gps_mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_gps_fd, target & ~(off_t)(page_size - 1));
    if (g_gps_map_base == (void *)-1)
    {
        printf ("NULL pointer!\n");
    }
    else
    {
        printf ("BSP gps map Successfull!\n");
    }
    fflush(stdout);

    g_gps_virt_addr = (char*)g_gps_map_base + offset_in_page;
    // printf("g_gps_virt_addr: %p %p %x\n", g_gps_virt_addr, g_gps_map_base, offset_in_page);

    // Init timer ccu clock
    /* set TMR3 clock source to HOSC, 8 pre-division */
    temp_ccu_base = g_ccu_map_base + 0x080C;
    read_result = *(volatile u_int32_t*)(temp_ccu_base);
	read_result &= ~(0x01 << 24);
    read_result |= (1 << 31) | 3;
    *(volatile u_int32_t*)(temp_ccu_base) = read_result;

    // Enable timer3
    /* set timer intervalue */
    temp_virt_l_base = (char*)g_gps_map_base + 0x84;
    temp_virt_h_base = (char*)g_gps_map_base + 0x8C;
    *(volatile u_int32_t*)(temp_virt_l_base) = 3000000;
    *(volatile u_int32_t*)(temp_virt_h_base) = 0x0;

	/* set mode to auto reload */
    temp_virt_ctl_base = (char*)g_gps_map_base + 0x80;
	read_result = *(volatile u_int32_t*)(temp_virt_ctl_base);
    read_result &= TIMER_CTL_PERIODIC;
    *(volatile u_int32_t*)(temp_virt_ctl_base) = (read_result | TIMER_CTL_AUTORELOAD | TIMER_CTL_ENABLE);
	
	/* Enable timer interrupt */
	temp_virt_irq_base = (char*)g_gps_map_base + 0x00;
	read_result = *(volatile u_int32_t*)(temp_virt_irq_base);
	*(volatile u_int32_t*)(temp_virt_irq_base) = (read_result | TIMER_IRQ_EN(3));

	/* Get linux system current time */
	clock_gettime(CLOCK_REALTIME, &ts);
	timespec_to_rtc(ts, &ct, 1);
	if(ct.hour>=24||ct.min>=60||ct.month>12||ct.day>31||ct.day==0||ct.month==0)  // 读取系统时钟错误
	{
		/* Reset linux system time */
		ct.year = 8;
		ct.month = 8;
		ct.day = 8;
		ct.hour = 8;
		ct.min = 8;
		rtc_to_timespec(&ct, &ts);
		rt_printf("gps read system date data error!!!");
	}

	g_sys_time.tv_sec = ts.tv_sec;
	g_sys_time.tv_nsec = ts.tv_nsec;

	init_timer_1ms_thread();

	return 0;
}

int timer_1ms(void* arg){

    cpu_set_t set;
    CPU_ZERO(&set);
    CPU_SET(3, &set);
    pid_t tid = syscall(SYS_gettid);
	sched_setaffinity(tid, sizeof(cpu_set_t), &set);
	
	printf("Thread created successfully: %s, PID: %d LWP: %d\r\n", 
              	"timer_1ms", (int)syscall(SYS_gettid), (int)syscall(SYS_gettid));
    while(1)
    {
		gps_isr();
        usleep(500);// 扫描间隔改为500us EWen
	}
	
	return 0;
}


void init_timer_1ms_thread(void)
{
	// 设置实时性
    pthread_attr_t attr;
    struct sched_param param;
    pthread_t thread;

    if (pthread_attr_init(&attr) != 0) {
        perror("pthread_attr_init failed");
        return;
    }

    if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
        perror("pthread_attr_setschedpolicy failed");
        goto cleanup;
    }

    param.sched_priority = 99;
    if (pthread_attr_setschedparam(&attr, &param) != 0) {
        perror("pthread_attr_setschedparam failed");
        goto cleanup;
    }

    if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) {
        perror("pthread_attr_setinheritsched failed");
        goto cleanup;
    }

    if (pthread_create(&thread, &attr, timer_1ms, NULL) != 0) {
        perror("pthread_create failed");
        goto cleanup;
    }

    // 分离线程
    pthread_detach(thread);
    
    printf("PPS线程已启动并在后台运行\n");

cleanup:
    pthread_attr_destroy(&attr);
}

int gps_exit(void)
{
	unsigned long read_result;
	void *temp_virt_ctl_base;
	if (g_gps_fd >= 0)
    {
        close(g_gps_fd);
        g_gps_fd = -1;
    }

	temp_virt_ctl_base = (char*)g_gps_map_base + 0x80;
	read_result = *(volatile u_int32_t*)(temp_virt_ctl_base);
	read_result &= ~(TIMER_CTL_ENABLE);
	*(volatile u_int32_t*)(temp_virt_ctl_base) = (read_result);

    if (munmap(g_gps_map_base, g_gps_mapped_size) == -1) {
        printf("munmap failed!");
        return -1;
    }

 	return 0;
}


int gps_get_time(struct timespec *p_ts)
{
	unsigned long flags;
    register long tv_sec,tv_nsec;
	unsigned long read_result;
	void *temp_virt_cvl_base, *temp_virt_irq_base;
	
	//检查参数
	if(p_ts == 0)
		return -1;
	
	//关中断
	rt_irq_save(flags);

	tv_sec = g_sys_time.tv_sec;

	temp_virt_cvl_base = (char*)g_gps_map_base + 0x88;
	temp_virt_irq_base = (char*)g_gps_map_base + 0x04;
	// read_result = *(volatile u_int32_t*)(temp_virt_cvl_base);
	tv_nsec = 3000000 - (*(volatile u_int32_t*)(temp_virt_cvl_base));

    if (((*(volatile u_int32_t*)(temp_virt_irq_base)) & (1 << 3)) != 0)
    {
        tv_sec += 1;
		tv_nsec = 3000000 - (*(volatile u_int32_t*)(temp_virt_cvl_base));
    }
	
	//恢复中断级别
	rt_irq_restore(flags);

	p_ts->tv_sec = tv_sec;
    p_ts->tv_nsec = (tv_nsec / 3) * 1000;

	return 0;
}

int gps_set_time(struct timespec *p_ts)
{
	unsigned int flags;
	unsigned int tmp;
	unsigned int read_result;
	void *temp_virt_cvl_base, *temp_virt_irq_base,*temp_virt_ctrl_base;

    if (!p_ts) {
		return -1;
	}
    
    rt_irq_save(flags);
    g_sys_time.tv_nsec = p_ts->tv_nsec;
    g_sys_time.tv_sec = p_ts->tv_sec;

	tmp = 3000000 - ((g_sys_time.tv_nsec / 1000) * 3);
    if (tmp > 3000000)
    tmp = 3000000;

	temp_virt_ctrl_base= (char*)g_gps_map_base + 0x80;
	temp_virt_cvl_base = (char*)g_gps_map_base + 0x88;

	read_result = *(volatile u_int32_t*)temp_virt_ctrl_base;
	read_result &= ~TIMER_CTL_ENABLE;
	*(volatile u_int32_t*)temp_virt_ctrl_base = read_result;

	*(volatile u_int32_t*)(temp_virt_cvl_base) = tmp;

	read_result |= (TIMER_CTL_ENABLE|TIMER_CTL_AUTORELOAD);
	*(volatile u_int32_t*)temp_virt_ctrl_base = read_result;
	// ((TIMER_TypeDef *) g_timer_base)->TMR3_CVH_REG = 0x0;

    rt_irq_restore(flags);
	
	
	return 0;
	
}

/******************************************************************************
函数名称：	gps_disable
函数版本：	01.01
创建作者：	
创建日期：	2014-12-02
函数说明：	禁止GPS输入功能。
参数说明：	无
返回值：  	无.
修改记录：	
*/
void gps_disable(void)
{
	MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) &= ~MCF_DTIM_DTMR_CE_ANY;	
}

/******************************************************************************
函数名称：	gps_enable
函数版本：	01.01
创建作者：	
创建日期：	2014-12-02
函数说明：	使能GPS输入功能。
参数说明：	无
返回值：  	无.
修改记录：	
*/
void gps_enable(void)
{
	MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) |= MCF_DTIM_DTMR_CE_ANY;		
}


/******************************************************************************
函数名称：	gps_reset
函数版本：	01.01
创建作者:	   sunxi
创建日期：	2008-08-06
函数说明：	gps对时模块复位。
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/
int gps_reset(void)
{
	//全局变量清零
	g_signal_valid = 0;
	g_keep_alive_gps = 0;
	g_irig_old_value = 0;
	g_irig_old_interval = 0;
	g_irig_code_index = 0;
	
	return 0;
}

/******************************************************************************
函数名称：	gps_pulse_isr
函数版本：	01.01
创建作者:	ocean
创建日期：	2023-11-24
函数说明：	gps脉冲中断
参数说明：	无
返回值：  	成功返回0.
修改记录：
*/
void gps_pulse_isr(void *data)
{
	unsigned int flags;

    rt_irq_save(flags);
    g_sys_time.tv_sec++;
    rt_irq_restore(flags);
}

/******************************************************************************
函数名称：	gps_isr
函数版本：	01.01
创建作者:	   sunxi
创建日期：	2008-08-06
函数说明：	gps中断处理函数。
参数说明：	无
返回值：  	成功返回0.
修改记录：	
*/

void gps_isr(void)
{
	void *temp_virt_cvl_base, *temp_virt_irq_base;
	// clear irq flags
    if (g_gps_map_base) {
		temp_virt_irq_base = (char*)g_gps_map_base + 0x04;
		if (((*(volatile u_int32_t*)(temp_virt_irq_base)) & (1 << 3)) != 0)
		{
			gps_pulse_isr(NULL);
			*(volatile u_int32_t*)(temp_virt_irq_base) = (1 << 3);
		}
    }
	
}

/*------------------------------ 内部函数 -------------------------------------
*/
//闰年判断
int _is_leap_year(int year)
{
	if ((((year & 0x3) == 0) && (year % 100 != 0)) ||(year % 400 == 0))
		return 1;
	else
		return 0;
}


//日期转换，给出一年中的第几天(从1开始，不是从0开始)，算出是这一年的几月几日
int _days_translate(struct rtc_time_t  * pt,int year,int day)
{
	static int month_last_day[2][13]=
	{
		{0,31,59,90,120,151,181,212,243,273,304,334,365},	//平年
		{0,31,60,91,121,152,182,213,244,274,305,335,366},	//闰年
	};

	int i;
	int *last_day;
	
	if(pt == 0 || day == 0 || day > 366)
		return -1;
	
	last_day = month_last_day[_is_leap_year(year)];
	
	for(i=0;i<13;i++)
	{
		if(day<=last_day[i])
		{
			break;
		}
	}
	
	pt->month = (unsigned char)i;
	pt->day = (unsigned char)(day-last_day[i-1]);
	
	return 0;
}

int _gps_irig_decode(unsigned char *code,struct rtc_time_t * p_tm )
{
#if 0
	 int tmp;
	//检查P码位置
	if(	  code[0]!=GPS_IRIG_CODE_P
		||code[9]!=GPS_IRIG_CODE_P
		||code[19]!=GPS_IRIG_CODE_P
		||code[29]!=GPS_IRIG_CODE_P
		||code[39]!=GPS_IRIG_CODE_P
		||code[49]!=GPS_IRIG_CODE_P
		||code[59]!=GPS_IRIG_CODE_P
		||code[69]!=GPS_IRIG_CODE_P
		||code[79]!=GPS_IRIG_CODE_P
		||code[89]!=GPS_IRIG_CODE_P)
		return -1;
	
	//秒
	tmp =	((code[8]<<2)+(code[7]<<1)+code[6])*10
		+(code[4]<<3)+(code[3]<<2)+(code[2]<<1)+(code[1]);
	if(tmp>=60)
		return -2;
	p_tm->ms = (unsigned short)(tmp*1000 + p_tm->ms%1000);
	
	//分
	tmp =	((code[17]<<2)+(code[16]<<1)+code[15])*10
		+(code[13]<<3)+(code[12]<<2)+(code[11]<<1)+(code[10]<<0);
	if(tmp>=60)
		return -3;
	p_tm->min=(unsigned char)tmp;
	
	//时
	tmp =	((code[26]<<1)+code[25])*10
		+(code[23]<<3)+(code[22]<<GPS_IRIG_CODE_P)+(code[21]<<1)+(code[20]<<0);
	if(tmp>=24)
		return -4;
	p_tm->hour=(unsigned char)tmp;

	if(g_clock_mode == CLOCK_MODE_GPS_B_YEAR_NONE)	
	{	
		//不带年的B码对时
		//日
		tmp =	 ((code[41]<<1)+code[40])*100
			+((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10
			+ (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30];
		if(tmp>366 || tmp == 0)
			return -5;
		
		p_tm->year = tmp_sys_time.year;
		_days_translate(p_tm,p_tm->year + 2000,tmp);
	}
	else if(g_clock_mode == CLOCK_MODE_GPS_B_YEAR)	
	{
		//带年的B码对时
		//日
		tmp=((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10+	
			(code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30];
		if(tmp>31||tmp==0)
			return -6;	
		p_tm->day = (unsigned char)tmp;
		
		//月
		tmp=(code[43]<<3)+(code[42]<<2)+(code[41]<<1)+code[40];
		if(tmp > 12)
		return -7;	
		p_tm->month = (unsigned char)tmp;	
		
		//年
		tmp=((code[58]<<3)+(code[57]<<2)+(code[56]<<1)+code[55])*10+	
			(code[53]<<3)+(code[52]<<2)+(code[51]<<1)+code[50];
		p_tm->year = (unsigned short)tmp;
	}
	else if(g_clock_mode == CLOCK_MODE_GPS_B_2009)
	{
		//年
		tmp=((code[58]<<3)+(code[57]<<2)+(code[56]<<1)+code[55])*10+	
			(code[53]<<3)+(code[52]<<2)+(code[51]<<1)+code[50];
		p_tm->year = (unsigned short)tmp;
		
		//日
		tmp =	 ((code[41]<<1)+code[40])*100
			+((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10
			+ (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30];
		if(tmp>366 || tmp == 0)
			return -8;
			
		_days_translate(p_tm,p_tm->year + 2000,tmp);	
			
	}
	
#endif
	return 0;
}


void _ms_update_time(void)
{
	struct rtc_time_t *pt = &tmp_sys_time;
	int day_flag = 0;
	
	if(pt->ms<60000)
		return;

	pt->ms = 0;
	pt->min++;
	if(pt->min>=60)
	{
		pt->min=0;
		pt->hour++;
		if(pt->hour>=24)
		{
			pt->hour=0;
			pt->day++;
			if(pt->month==2)  
			{
				// 2月
				if(pt->day>28)
				{
					if(_is_leap_year(pt->year+2000))  
					{
						//闰年 2月29天?
						if(pt->day>29)
						{
							day_flag=1;
						}
					}
					else
					{
						//其他28天
						day_flag=1;
					}
				}
			}
			else
			{
				//非2月
				if(pt->day>30)
				{
					if(pt->month==4||pt->month==6||pt->month==9||pt->month==11)
					{
						day_flag=1;					
					}
				}
				if(pt->day>31)
				{
					day_flag=1;					
				}
			}
			
			if(day_flag)
			{
				pt->day = 1;
				pt->month++;
				if(pt->month>12)
				{
					pt->month=1;
					pt->year++;
				}
			}
		}
	}
}

void _gps_1s_isr(void)
{

	//unsigned int now;
	//uint32_t  flags;
	#if 0
	if(tmp_sys_time.ms%2 == 0)
	{
//		DIO_KOUT6_OFF();

	}
	else
	{
//		DIO_KOUT6_ON();
	}
	
	//计数
	tmp_sys_time.ms ++;

	//输出对时脉冲(10ms,下降沿)
	if((tmp_sys_time.ms%1000) >= 10 )
	{
		//GPIO_GPS_HIGH();
	}
	else if(tmp_sys_time.ms%1000 != 0)
	{
		//GPIO_GPS_LOW();
	}
	
	else 
	{
		//tmp_sys_time.ms%1000 == 0的情况
		if(g_clock_mode == CLOCK_MODE_EXT || g_clock_mode == CLOCK_MODE_GPS_MINUTE)
		{
			//当对时模式为外部对时或分对时的时候，在这儿输出下降沿。
			//GPIO_GPS_LOW();
		}
		else if(g_signal_valid == 0)
		{
			//输入信号不合法，在此输出下降沿
			//GPIO_GPS_LOW();
		}
	}
	#endif

	rt_irq_save(flags);
	
	g_sys_time.tv_sec++;
	g_1s_refence +=  1000000;
	MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
	
	rt_irq_restore(flags);
	

	//更新系统时间
	//_ms_update_time();
	
	//GPS保活处理
	if(g_keep_alive_gps)
	{
		// 减1s
		g_keep_alive_gps -= 1000;
	}
	
	return;
}


void _gps_capture_isr(void)
{
#if 0
	unsigned int interval,capture_value,n;
	
	//如果不是GPS对时模式，不进行任何处理
//	if(g_clock_mode == CLOCK_MODE_EXT)
		return;
	
	//得到计数值,并计算和上一次计数器之差,也就是两次中断之间的计数值.
	capture_value = MCF_REG32(MCF_DTIM_DTCR(CFG_DTIM_GPS_CAP));	
	interval = (capture_value  - g_irig_old_value + 500L)/1000;
	
	//消除干扰信号
	if(interval < 2)
	{
		rt_printf("gps:interval = %d\r\n",interval);
		
		//干扰信号，直接返回
		return;
	}
	

#if 0
	if(GPIO_GPS_INT_STATUS())
		rt_printf("H:");
	else
		rt_printf("L:");
	rt_printf("%d,%d\r\n",capture_value  - g_irig_old_value,capture_value);
	goto __ret;
#endif

	if(g_clock_mode == CLOCK_MODE_GPS_SECOND)
	{
		//输入信号不为低电平时不进行逻辑判断。
		//注意：目前输入信号经过了两个反相器。
		if(GPIO_GPS_INT_STATUS() == 0)
		{
			goto __ret;
		}
		
		//检查输入信号正负脉冲之和是否为1000ms.
		n = interval + g_irig_old_interval;
		//if( n < 999 || n > 1001)
		if( abs(n - 1000) > GPS_SIGAL_DIFF)
		{	//输入信号不正常，重新搜索秒开始位置
			rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval);
			
			g_signal_valid = 0;
			goto __ret;
		}
		
		//分板对时下降沿
		//GPIO_GPS_LOW();
		
		//修正时间
		tmp_sys_time.ms = (unsigned short)((tmp_sys_time.ms+500)/1000*1000);
		_ms_update_time();

		//修正边沿
		MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
		g_1s_refence = capture_value + 1000000;
		MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
		
		//GPS保活
		g_keep_alive_gps = CLOCK_ALIVE_GPS;
		
		g_signal_valid = 1;
		
		goto __ret;
		
	}
	
	if(g_clock_mode == CLOCK_MODE_GPS_MINUTE)
	{
		//输入信号不为低电平时不进行逻辑判断。
		//注意：目前输入信号经过了两个反相器。
		if(GPIO_GPS_INT_STATUS() == 0)
		{
			goto __ret;
		}
		
		//检查输入信号正负脉冲之和是否为1分钟。
		//由于我们使用的晶体是50ppm的，在一分钟之内可能有3ms的误差，
		//所以我们以5ms作为指标判断。
		n = interval + g_irig_old_interval;
		if( n < (60*1000 - 5) || n > (60*1000 + 5))
		{	//输入信号不正常，重新搜索分开始位置
			rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval);
			
			g_signal_valid = 0;
			goto __ret;;
		}
		
		//分板对时下降沿
		//GPIO_GPS_LOW();
		
		//修正时间
		if(tmp_sys_time.ms > 30000)
		{
			tmp_sys_time.ms = 60000;
			_ms_update_time();
		}
		else
		{
			tmp_sys_time.ms = 0;
		}
		
		//修正边沿
		MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
		g_1s_refence = capture_value + 1000000;
		MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
		
		//GPS保活
		g_keep_alive_gps = CLOCK_ALIVE_GPS + 60000;

		g_signal_valid = 1;
		goto __ret;
	}
	
	//!!!以下为B码对时
	//检查输入信号
	if(abs(interval - 2)> GPS_SIGAL_DIFF && abs(interval - 5) > GPS_SIGAL_DIFF && abs(interval - 8) > GPS_SIGAL_DIFF)
	{
		rt_printf("gps:%d\r\n",interval);
		
		//输入信号不正常，重新搜索秒开始位置
		g_signal_valid = 0;
		g_irig_code_index = 0;
		goto __ret;
		
	}
	
	//输入信号不为低电平时不进行逻辑判断。
	//注意：目前输入信号经过了两个反相器。
	if(GPIO_GPS_INT_STATUS() == 0)
	{
		goto __ret;
	}
	
	//检查输入信号正负脉冲之和是否为10ms。
	if(abs(interval + g_irig_old_interval - 10) > GPS_SIGAL_DIFF)
	{	//输入信号不正常，重新搜索秒开始位置
		rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval);
		
		g_signal_valid = 0;
		g_irig_code_index = 0;
		goto __ret;;
	}

	//如果g_irig_code_index<2，需要搜索秒开始位置
	if(g_irig_code_index <2)
	{
		//如果不是P码，放弃处理，重新搜索。	
		if(abs(g_irig_old_interval - 8) > GPS_SIGAL_DIFF)
		{
			g_signal_valid = 0;
			g_irig_code_index = 0;
			
			goto __ret;
		}
		
		//保存P码
		g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_P;
		
		
		if(g_irig_code_index == 1 && g_signal_valid == 1)
		{
			//分板对时下降沿
			//GPIO_GPS_LOW();
			
			//修正时间
			tmp_sys_time.ms = (unsigned short)((tmp_sys_time.ms+500)/1000*1000);
		    _ms_update_time();
			
			//修正边沿
			MCF_REG32(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF;
			g_1s_refence = capture_value + 1000000;
			MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence;
		}

		goto __ret;	
	}
	
	//保存编码
	switch(g_irig_old_interval)
	{
	case 1:
	case 2:
	case 3:
		g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_0;
		break;
	case 4:	
	case 5:
	case 6:
		g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_1;
		break;

	case 7:
	case 8:
	case 9:
		g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_P;
		break;
		
	default:
		rt_printf("gps:g_irig_old_interval=%d!\r\n",g_irig_old_interval);
		
		g_signal_valid = 0;
		g_irig_code_index = 0;
		goto __ret;
		break;
	}
		

	//如果接收完时间信息，就开始处理
	if(g_irig_code_index >= 100)
	{
		if(_gps_irig_decode(&g_irig_code[1],&tmp_sys_time) == 0)
		{
			g_signal_valid = 1;
			g_keep_alive_gps = CLOCK_ALIVE_GPS;
		}
		else
			g_signal_valid = 0;	
				
		g_irig_code_index = 0;
	}

__ret:	
	g_irig_old_value = capture_value;
	g_irig_old_interval = interval;
#endif	
}


/*------------------------------ 测试函数 -------------------------------------
*/
#ifdef _DEBUG_GPS

#include "ustimer.h"

int gps_test(void)
{

	unsigned int us0,t;
		
	rt_printf("gps_test start...\r\n");
	
//	rt_irq_level(0);
	
	t = 0;
	us0 = ustimer_get_origin();
	// sunxi 20220424 while(1) ;
	while(t < 10)
	{
	//	rt_printf("pit(t=%03dsec):g_gps_ms:%06d,diff(g_gps_ms-t*1000):%d!\r\n",t,g_gps_ms,g_gps_ms -t*1000);
		rt_printf("g_sys_time: %04d-%02d-%02d time: %02d:%02d:%05d!\r\n",
				tmp_sys_time.year + 2000,
				tmp_sys_time.month,
				tmp_sys_time.day,
				tmp_sys_time.hour,
				tmp_sys_time.min,
				tmp_sys_time.ms
				);
	
		ustimer_delay_origin(us0,++t*USTIMER_SEC);
	}
	
	rt_printf("gps_test end...\r\n");
	
	return 0;
}
#endif

