/*--------------------------------------------------------------------------------------
*  @file     FM31256.c
*  @author   ZhangJing
*  @version  base on stm32f0x   
*  @date     2015.09.11
*  @brief    FM31256驱动
---------------------------------------------------------------------------------------*/


/*--------------------------------------------------------------------------------------
*  @file     FM31256.c
*  @author   ZhangJing
*  @version  base on stm32f0x   
*  @date     2015.09.11
*  @brief    FM31256驱动
---------------------------------------------------------------------------------------*/
#include "stm32f10x_gpio.h"
#include "TypeDefine.h"
#include "IICSetup.h"
#include "FM31256.h"

/*************************************************************************************
*  Function:	hex_to_bcd			                                                           
*  Object:		十六进数转换成BCD码
*  输入:			unsigned char  condata需转换数据
*  输出:			转换完成的BCD码	                                     
*  备注:			unsigned char temp;
							unsigned char temp0;
							unsigned char temp10; 做数据计算的临时变量
**************************************************************************************/
unsigned char  hex_to_bcd(unsigned char  condata)
{
	unsigned char temp;
	unsigned char temp0;
	unsigned char temp10;
	temp10=condata/10;
	temp0=condata%10;
	temp=(temp10<<4)|temp0;
	return(temp);
}

/*************************************************************************************
*  Function:	bcd_to_hex			                                                           
*  Object:		BCD码转换成十六进制数
*  输入:			unsigned char  condata需转换数据
*  输出:			转换完成的BCD码	                                     
*  备注:			unsigned char temp;
							unsigned char temp0;
							unsigned char temp10; 做数据计算的临时变量
**************************************************************************************/
unsigned char bcd_to_hex(unsigned char condata)
{
	unsigned char temp;
	unsigned char temp0;
	unsigned char temp10;
	temp10=(condata&0xF0)>>4;
	temp0=condata&0x0F;
	temp=temp10*10+temp0;
	return(temp);
}

/*************************************************************************************
*  Function:	Read_Reg			                                                           
*  Object:		读取FM31256寄存器
*  输入:			unsigned char addr, 读取地址 unsigned char *ucDataPtr 读取数据存储指针
*  输出:			返回读取状态                                    
*  备注:			unsigned char read_data=0xaa;读取数据
							unsigned char tempState = 0;状态值
**************************************************************************************/
unsigned char  Read_Reg(unsigned char addr, unsigned char *ucDataPtr)
{
	unsigned char read_data=0xaa;
	unsigned char tempState = 0;
  
	//启动
	if(RTC_START()!=RTC_READY)
		return 0;
	//TWI_START();

	//从机地址写入
	tempState = RTC_SendByte( Const_REG_ADDR + Const_IIC_WRITE );
	//tempState = TWI_SendByte( Const_REG_ADDR + Const_IIC_WRITE );

	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		//TWI_STOP();
		return( tempState );
	}

	//输出地址
	tempState = RTC_SendByte( addr );
	//tempState = TWI_SendByte( addr );
	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		//TWI_STOP();  
		return( tempState );
	}
	
	//启动
	if(RTC_START()!=RTC_READY)
		return 0;
	//TWI_START();

	//从机地址写入
	tempState = RTC_SendByte( Const_REG_ADDR + Const_IIC_READ );
	//tempState = TWI_SendByte( Const_REG_ADDR + Const_IIC_READ );
	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		//TWI_STOP();    
		return( tempState );
	}
	
	read_data = RTC_ReceiveByte();
  //read_data = TWI_ReceiveByte();
	
	RTC_STOP();
  //TWI_STOP();
	*ucDataPtr=read_data;
	
	return 1;	
}


/*************************************************************************************
*  Function:	Write_Reg			                                                           
*  Object:		写FM31256寄存器
*  输入:			unsigned char addr, 写入地址 unsigned char data 写入数据
*  输出:			返回写入状态                                    
*  备注:			unsigned char tempState = 0;状态值
**************************************************************************************/
unsigned char  Write_Reg(unsigned char addr,unsigned char data)
{
	unsigned char tempState = 0;
	

	//启动
	if(RTC_START()!=RTC_READY)
		return 0;
	//TWI_START();
	
	//从机地址写入
	tempState = RTC_SendByte( Const_REG_ADDR + Const_IIC_WRITE ); 	
	//tempState = TWI_SendByte( Const_REG_ADDR + Const_IIC_WRITE ); 	
	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		//TWI_STOP();
		return( tempState );
	}
	
	//输出地址
	tempState = RTC_SendByte( addr );
	//tempState = TWI_SendByte( addr );
	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		//TWI_STOP(); 
		
		return( tempState );
	}
	  
	//输出地址
	tempState = RTC_SendByte( data );
	//tempState = TWI_SendByte( data );
	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		//TWI_STOP(); 
		
		return( tempState );
	} 	
	
	RTC_STOP();
   //TWI_STOP();
	
	return 1;
}

/*********************************************************************************
*  Function:	Read_FM31256RAM			                                                           
*  Object:		单个读出RAM寄存器
*  输入:			RAM寄存器地址 ，读取数据存储指针
*  输出:			无
*  返回值:		1:读正常; 非1值:从机无应答
*  备注:			uint8_t tempState = 0;状态值
							uint8_t tempAddr = 0;  地址计算变量            
**********************************************************************************/
uint8_t Read_FM31256RAM( uint16_t uiAddr , uint8_t *ucDataPtr )
{
	uint8_t tempState = 0;
	uint8_t tempAddr = 0;

	//启动
	if( RTC_START() != RTC_READY )
	{
		return 0;
	}

	//从机地址写入	
	tempState = RTC_SendByte( Const_RAM_ADDR + Const_IIC_WRITE );
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}

	//输出地址
	tempAddr = ( uiAddr >> 8 ) & 0xff;//addr_h
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志 
		return( tempState );
	}

	tempAddr = uiAddr & 0xff;//addr_l
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志 
		return( tempState );
	}

	//启动
	if( RTC_START() != RTC_READY )
	{
		return 0;
	}

	//从机地址写入
	tempState = RTC_SendByte( Const_RAM_ADDR + Const_IIC_READ );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志  
		return( tempState );
	}

	*ucDataPtr  = RTC_ReceiveByte();

	RTC_STOP();

	return 1;	
}

/*********************************************************************************
*  Function:	Read_Multi31256RAM			                                                           
*  Object:		连续读出RAM寄存器
*  输入:			RAM寄存器地址
*  输出:			无   
*  返回值:		1:读正常; 非1值:从机无应答
*  备注:			uint8_t tempState = 0;状态值
							uint8_t tempAddr = 0;  地址计算变量                 
**********************************************************************************/
uint8_t Read_Multi31256RAM( uint16_t uiAddr, uint8_t *ucDataBufPtr, uint16_t uiLen )
{
	uint8_t tempState = 0;	
	uint8_t tempAddr = 0;
	uint8_t iN = 0;
	
	//判断地址是否越界
	if( ( uiAddr + uiLen ) > MAX_31256RAM_ADDRESS )
	{
		return( 3 );
	}
	
	RTC_SendNACK();	//不发送应答
	RTC_STOP();			//发送终止I2C标志	
	
	if( RTC_START() != RTC_READY )	//启动
	{
		return 0;
	}
	
	//从机地址写入	
	tempState = RTC_SendByte( Const_RAM_ADDR + Const_IIC_WRITE );
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}
	
	//输出地址
	tempAddr = ( uiAddr >> 8 ) & 0xff;//addr_h
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志 
		return( tempState );
	}

	tempAddr = uiAddr & 0xff;//addr_l
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志 
		return( tempState );
	}

	//启动
	if( RTC_START() != RTC_READY )
	{
		return 0;
	}

	//从机地址写入
	tempState = RTC_SendByte( Const_RAM_ADDR + Const_IIC_READ );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志  
		return( tempState );
	}
	
	for( iN = 0; iN < ( uiLen - 1 ); iN++ )
	{  

		*( ucDataBufPtr+iN ) = RTC_ReceiveByte(); //读数据

		RTC_SendACK();              //发送应答      

	}

	*( ucDataBufPtr + iN )=RTC_ReceiveByte(); //读数据 

	RTC_SendNACK();          //最后一个字节不发送应答   
	
	RTC_STOP();

	return 1;	
}

/*********************************************************************************
*  Function:	Write_FM31256RAM			                                                           
*  Object:		单个写入RAM寄存器
*  输入:			RAM寄存器地址
*  输出:			无   
*  返回值:		1:读正常; 非1值:从机无应答
*  备注:			uint8_t tempState = 0;状态值
							uint8_t tempAddr = 0;  地址计算变量                 
**********************************************************************************/
uint8_t  Write_FM31256RAM( uint16_t uiAddr , uint8_t ucData )
{
	uint8_t tempState = 0;	
	uint8_t tempAddr = 0;

	//启动
	if( RTC_START() != RTC_READY )
	{
		return 0;
	}
	
	//从机地址写入
	tempState = RTC_SendByte( Const_RAM_ADDR + Const_IIC_WRITE ); 	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}
	
	//输出地址
	tempAddr = ( uiAddr >> 8 ) & 0xff;//addr_h
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}
	tempAddr = uiAddr & 0xff;//addr_l
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}
	  
	//写入单个数据
	tempState = RTC_SendByte( ucData );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	} 	
	
	RTC_STOP();
	
	return 1;
}

/*********************************************************************************
*  Function:	Write_Multi31256RAM			                                                           
*  Object:		连续写入RAM寄存器
*  输入:			RAM寄存器地址
*  输出:			无   
*  返回值:		1:读正常; 非1值:从机无应答
*  备注:			uint8_t tempState = 0;状态值
							uint8_t tempAddr = 0;  地址计算变量                 
**********************************************************************************/
uint8_t Write_Multi31256RAM( uint16_t uiAddr , uint8_t *ucDataBufPtr , uint16_t uiLen )
{
	uint8_t tempState = 0;	
	uint8_t tempAddr = 0;
	uint8_t iN = 0;
	
	//判断地址是否越界
	if( ( uiAddr + uiLen ) > MAX_31256RAM_ADDRESS )
	{
		return( 3 );
	}
	
	RTC_SendNACK();	//不发送应答
	RTC_STOP();			//发送终止I2C标志	
	
	if( RTC_START() != RTC_READY )	//启动
	{
		return 0;
	}
	
	//从机地址写入	
	tempState = RTC_SendByte( Const_RAM_ADDR + Const_IIC_WRITE );
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}
	
	//输出地址
	tempAddr = ( uiAddr >> 8 ) & 0xff;//addr_h
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}
	tempAddr = uiAddr & 0xff;//addr_l
	tempState = RTC_SendByte( tempAddr );	
	if( 1 != tempState )
	{	    
		RTC_STOP();           //发送终止I2C标志
		return( tempState );
	}
	
	//连续写入数据
	for( iN = 0 ; iN < uiLen; iN++ )
	{
		tempState = RTC_SendByte( *( ucDataBufPtr + iN ) );	
		if( 1 != tempState )
		{	    
			RTC_STOP();           //发送终止I2C标志
			return( tempState );
		} 	
	}

	RTC_STOP();           //发送终止I2C标志

	return(1);
}


/*********************************************************************************
*  Function:	InitRtc			                                                           
*  Object:		FM31256初始化
*  输入:			无
*  输出:			无   
*  备注:			可初始化时间及工作电压               
**********************************************************************************/
void InitRtc(void)
{
    
  Write_Reg(Const_CONTROL,0);
  
  //Write_Reg(0,2);//??
  Write_Reg(Const_YEAR,hex_to_bcd(13));
  Write_Reg(Const_MONTH,hex_to_bcd(8));
  Write_Reg(Const_DATE,hex_to_bcd(26));
  Write_Reg(Const_WEEK,hex_to_bcd(3));
  Write_Reg(Const_HOURS,hex_to_bcd(13));
  Write_Reg(Const_MINUTES,hex_to_bcd(13));
  Write_Reg(Const_SECONDS,hex_to_bcd(15));
  //Write_Reg(0,0);//????
  //Write_Reg(1,0);
  //Write_Reg(Const_COMPANION,1);//无保护、充电（7）无充电（3）、复位电压4.4V
  
}

/*********************************************************************************
*  Function:	GetCurDateTimeFromRTC			                                                           
*  Object:		获取当前时间
*  输入:			无
*  输出:			无   
*  备注:			uint8_t ucTimeBuf[8];   
							uint8_t ucTempTime = 0; 读取时间计算变量          
**********************************************************************************/
void GetCurDateTimeFromRTC( void )
{	
	uint8_t ucTimeBuf[8];   
	uint8_t ucTempTime = 0;

	RTC_STOP();

	//Write_Reg(0,1);

// 	Read_Reg(Const_SECONDS,&ucTimeBuf[0]);

	Read_Reg(Const_MINUTES,&ucTimeBuf[1]);

	Read_Reg(Const_HOURS,&ucTimeBuf[2]);

// 	Read_Reg(Const_WEEK,&ucTimeBuf[3]);

	Read_Reg(Const_DATE,&ucTimeBuf[4]);//Const_DAY

	Read_Reg(Const_MONTH,&ucTimeBuf[5]);

	Read_Reg(Const_YEAR,&ucTimeBuf[6]);

	//Write_Reg(0,0);

	ucTempTime = bcd_to_hex(ucTimeBuf[6]);
	if( ucTempTime >= 15 && ucTempTime <= 99 )
	{
		displayTimeBuf.year = ucTempTime + 2000;
	}
	
	ucTempTime = (bcd_to_hex(ucTimeBuf[5]) & 0x1f);
	if( ucTempTime >= 1 && ucTempTime <= 12 )
	{
		displayTimeBuf.month = ucTempTime;
	}
	
	ucTempTime = (bcd_to_hex(ucTimeBuf[4]) & 0x3f);
	if( ucTempTime >= 1 && ucTempTime <= 31 )
	{
		displayTimeBuf.date = ucTempTime;
	}

	ucTempTime = ( bcd_to_hex(ucTimeBuf[2]) & 0x3f);
	if( ucTempTime <= 23 )
	{
		displayTimeBuf.hour = ucTempTime;
	}
	
	ucTempTime = (bcd_to_hex(ucTimeBuf[1])& 0x7f);
	if( ucTempTime <= 59 )
	{
		displayTimeBuf.minute = ucTempTime;
	}
	
	ucTempTime = (bcd_to_hex(ucTimeBuf[0]) & 0x7f);
	if( ucTempTime <= 59 )
	{
		displayTimeBuf.seconds = ucTempTime;
	}
}


/*********************************************************************************
*  Function:	SetDateTimeToRTC			                                                           
*  Object:		向FM31256设置时间
*  输入:			无
*  输出:			无   
*  备注:			根据displayTimeBuf结构体的数据向FM31256设置时间        
**********************************************************************************/
void SetDateTimeToRTC( void )
{
	if( displayTimeBuf.year < 2021 )
	{
		displayTimeBuf.year = 2021;
	}
 /* Write_Reg(0,0);
  
  Write_Reg(0,2);//使能*/
	
	Write_Reg(Const_CONTROL,0);
  
  //Write_Reg(0,2);//使能*/
	
  Write_Reg(Const_YEAR,hex_to_bcd(displayTimeBuf.year - 2000));
  Write_Reg(Const_MONTH,(hex_to_bcd(displayTimeBuf.month) & 0x1f));
  Write_Reg(Const_DATE,(hex_to_bcd(displayTimeBuf.date) & 0x3f));
  Write_Reg(Const_HOURS,(hex_to_bcd(displayTimeBuf.hour) & 0x3f));
  Write_Reg(Const_MINUTES,(hex_to_bcd(displayTimeBuf.minute) & 0x7f));
  Write_Reg(Const_SECONDS,(hex_to_bcd(displayTimeBuf.seconds)  & 0x7f));
  //Write_Reg(0,0);//关闭读写
  Write_Reg(Const_FLAGS,0);
}	


