/*==========================================================
函数名称:init_RCC_JJY
函数功能:初始化JJY接收参数,重新启动接收
输入参量:
输出参量:
==========================================================*/
void init_RCC_JJY(void)
{
	JJY_status = 0;
	JJY_TCO_time = 0;
	JJY_TCO_new_time = 0;
	JJY_sync_time = 0;

	for(JJY_counter=0;JJY_counter<_JJY_BUF;JJY_counter++)
	{
		JJY_buf[JJY_counter]=0;
	}
	
	JJY_counter = 0;
}





/*==========================================================
函数名称:JJY_encoder
函数功能:将接收到的JJY编码转换为时间代码
输入参量:
输出参量:
==========================================================*/
void JJY_encoder(void)
{
	unsigned short temp_day;
	unsigned char i,j,k,z;

	
	//BCD CODE to HEX
	JJY_second = 0;

	JJY_minute = ((JJY_buf[7]&0x7)*10) + ((JJY_buf[6]>>3)&0xf);

	JJY_hour = ((JJY_buf[5]>>6)*10) + ((JJY_buf[5]>>1)&0xf);

	temp_day = (((JJY_buf[4]>>4&0x3))*100) + (((JJY_buf[4]<<1)&0xf)*10) + ((JJY_buf[3]>>7)*10) + ((JJY_buf[3]>>2)&0xf);

	JJY_year = (((JJY_buf[2]<<1)&0xf)*10) + ((JJY_buf[1]>>7)*10) + ((JJY_buf[1]>>3)&0xf);

	JJY_week = ((JJY_buf[1]<<1)&0x7) + (JJY_buf[1]>>7);


	JJY_day = 1;
	JJY_month = 1;

	while(temp_day) //总日期转换为月份和日期
	{
		if((JJY_month==1)||(JJY_month==3)||(JJY_month==5)||(JJY_month==7)\
		||(JJY_month==8)||(JJY_month==10)||(JJY_month==12))
		{
			i=31;
		}
		else if((JJY_month==4)||(JJY_month==6)||(JJY_month==9)||(JJY_month==10))
		{
			i=30;
		}
		else
		{
			if(JJY_year%4==0)
			{
				i=29;
			}
			else
			{
				i=28;
			}
		}

		if(temp_day > i)
		{
			temp_day-=i;
			JJY_month++;
		}
		else
		{
			JJY_day = temp_day;
			temp_day=0;
		}
	};

	//在这后面加入校验，可在一定程度上防止出错
	i=1;
	j=1;
	z=0;
	
	for(k=0;k<8;k++)
	{
		if(JJY_hour&j)
		{
			z++;
		}
		
		j<<=1;
	}
	
	if((JJY_buf[2]>>7) != (z&0x1))	//小时奇偶校验
	{
		i=0;
	}

	j=1;z=0;
	for(k=0;k<8;k++)
	{
		if(JJY_minute&j){z++;}
		j<<=1;
	}
	if(((JJY_buf[2]>>6)&0x1) != (z&0x1)) {i=0;}	//分钟奇偶校验

	if((i==1)\				//奇偶校验
	&&(JJY_minute<60)\			//分钟校验
	&&(JJY_hour<24)\			//小时校验
	&&((JJY_day>=1)&&(JJY_day<=31))\	//日期校验
	&&((JJY_month>=1)&&(JJY_month<=12))\	//月份校验
	&&(JJY_year<=99))			//年份校验
	{
		//校验正确,将数据送给实时时钟

		//.................

		//.................

	}
	else
	{
		//校验出错,得重新接收
		JJY_status &= (~_JJY_START_F);
		JJY_status &= (~_JJY_OK_F);
		JJY_counter=0;
	}
}




/*==========================================================
函数名称:save_TCO_code
函数功能:保存一位接收到的编码
输入参量:
输出参量:
==========================================================*/
void save_TCO_code(unsigned char TCO_code)
{
	unsigned char i;

	
	for(i=_JJY_BUF-1;i>0;i--)
	{
		JJY_buf[i] <<= 1;
		
		if(JJY_buf[i-1]&0x80)
		{
			JJY_buf[i] |= 0x1;
		}
	}

	JJY_buf[0] <<= 1;
	
	if(TCO_code)
	{
		JJY_buf[0] |= 0x1;
	}

	if(++JJY_counter >= _MAX_JJY_CODE)
	{
		JJY_encoder(); //JJY解码

		JJY_status |= _JJY_OK_F;
	}
}



/*==========================================================
函数名称:Receiver_JJY
函数功能:JJY接收程序
输入参量:
输出参量:
==========================================================*/
void Receiver_JJY(void)
{
	unsigned char new_tco,new_code;

	
	if(JJY_status&_JJY_OK_F) return;

#if(TCO_SIGNAL_LEVEL == 1)
	if(TCO_IN)
	{
		new_tco = 1;
	}
	else
	{
		new_tco = 0;
	}
#else
	if(TCO_IN)
	{
		new_tco = 1;
	}
	else
	{
		new_tco = 0;
	}
#endif

	if(++JJY_sync_time >= 100)
	{
		JJY_sync_time = 0;
		JJY_TCO_new_time = 0;
	}

	if(((new_tco)&&(!(JJY_status&_JJY_TCO_F)))||(!(new_tco)&&(JJY_status&_JJY_TCO_F)))
	{
		if(++JJY_TCO_new_time >= _NEW_TCO_TIME) //新的数据有效
		{
			if((JJY_TCO_time>=(_TCO_0_TIME-_TCO_OFFSET_TIME))&&(JJY_TCO_time<=(_TCO_0_TIME+_TCO_OFFSET_TIME)&&(JJY_status&_JJY_TCO_F)))
			{
				new_code=_TCO_CODE_0;
			}
			else if((JJY_TCO_time>=(_TCO_1_TIME-_TCO_OFFSET_TIME))&&(JJY_TCO_time<=(_TCO_1_TIME+_TCO_OFFSET_TIME)&&(JJY_status&_JJY_TCO_F)))
			{
				new_code=_TCO_CODE_1;
			}
			else if((JJY_TCO_time>=(_TCO_P_TIME-_TCO_OFFSET_TIME))&&(JJY_TCO_time<=(_TCO_P_TIME+_TCO_OFFSET_TIME)&&(JJY_status&_JJY_TCO_F)))
			{
				new_code=_TCO_CODE_P;
			}
			else if(JJY_status&_JJY_TCO_F)
			{
				new_code=_TCO_CODE_ERR;
			}

			if(!(JJY_status&_JJY_SYNC_F)) //准备时间同步
			{
				if(!(JJY_status&_JJY_TCO_F))
				{
					if((JJY_sync_time<=_SYNC_OFFSET_TIME)||(JJY_sync_time>=(100-_SYNC_OFFSET_TIME)))
					{
						if(++JJY_counter >= _SYNC_TIME)
						{
							JJY_status |= _JJY_SYNC_F;
							JJY_counter = 0;
						}
					}
					else
					{
						JJY_counter = 0;
					}

					JJY_sync_time = JJY_TCO_new_time;
				}
			}
			else if(!(JJY_status&_JJY_START_F)) //启动信号
			{
				if(JJY_status&_JJY_TCO_F)
				{
					if((JJY_TCO_code==_TCO_CODE_P)&&(new_code==_TCO_CODE_P))
					{
						JJY_status|=_JJY_START_F;
						for(JJY_counter=0;JJY_counter<_JJY_BUF;JJY_counter++)
						{
							JJY_buf[JJY_counter]=0;
						}

						JJY_counter = 0;
						save_TCO_code(0);
					}
					else if(++JJY_counter >= _MAX_START_TIME)
					{
						init_RCC_JJY(); //防止同步时间出错后收不到
					}
				}
			}
			else if(JJY_status&_JJY_TCO_F)//接收数据
			{
				if((new_code==_TCO_CODE_0)||(new_code==_TCO_CODE_P))
				{
					save_TCO_code(0);
				}
				else if(new_code==_TCO_CODE_1)
				{
					save_TCO_code(1);
				}
				else //出错了,重来
				{
					for(JJY_counter=0;JJY_counter<_JJY_BUF;JJY_counter++)
					{
						JJY_buf[JJY_counter]=0;
					}
					JJY_counter = 0;
					JJY_status &= (~_JJY_START_F);
				}

				if((JJY_TCO_code==_TCO_CODE_P)&&(new_code==_TCO_CODE_P))
				{
					if(!(JJY_status&_JJY_OK_F)) //发现新的同步信号,重来
					{
						for(JJY_counter=0;JJY_counter<_JJY_BUF;JJY_counter++)
						{
							JJY_buf[JJY_counter]=0;
						}
						JJY_counter = 0;
					}
				}
			}

			if(JJY_status&_JJY_TCO_F)
			{
				JJY_TCO_code = new_code;
			}

			if(new_tco)
			{
				JJY_status |=_JJY_TCO_F;
			}
			else
			{
				JJY_status &= ~_JJY_TCO_F;
			}

			JJY_TCO_time = JJY_TCO_new_time;
			JJY_TCO_new_time=0;
		}
	}
	else
	{
		if(JJY_TCO_new_time > 0)
		{
			JJY_TCO_time += JJY_TCO_new_time;
			JJY_TCO_new_time=0;
		}

		if(JJY_TCO_time < 100)
		{
			JJY_TCO_time++;
		}
	}
}