/*C*****************************************************************************
* NAME:         at45db.c
*-------------------------------------------------------------------------------
* RELEASE:          
* REVISION:     1.0   
*-------------------------------------------------------------------------------
* PURPOSE:
* at45Db驱动。
*******************************************************************************/
/*_____ I N C L U D E S ______________________________________________________*/	
#include "config.h"	 	//全局声明
u8 FlashType = 0;
F_uniGlobal_Typedef   F_uniGlobal;
#define Data_INIT
const u8 initATDB45_Flag = 0x38;
const PREXDATA_Type initPREXDATA = {0,0,0,0,0,0,0,0,0};
const AT45DBDataIndex AT45DBTab[20] =
{	///FRAM数据1区(数据操作相对不频烦)	 
///	pInitData;			      upData					      pData				         firstAdr;	                    len;			                    Tpye;	 //(注意,校验增加在数据包尾)	
  {(u8*)&initATDB45_Flag,           (u8*)(&buf_ATDB45_Flag),      (u8*)(&TXHData.ATDB45_Flag),     ATDB45_Flag_FADR,      ATDB45_Flag_LEN,      ATDB45_Flag_Group,       CA_ATDB45_Flag},
  {(u8*)&initATDB45_Flag,           (u8*)(&buf_Frame),            (u8*)(&TXHData.Frame),           Frame_FADR,            Frame_LEN,            Frame_Group,             CA_Frame},
	{(u8*)&initPREXDATA,              (u8*)(&buf_PREXDATA),         (u8*)(&TXHData.PREXDATA),        PREXDATA_FADR,         PREXDATA_LEN,         PREXDATA_Group,          CA_PREXDATA},
	{(u8*)&initATDB45_Flag,           (u8*)(&buf_DeviceFrame),      (u8*)(&TXHData.Frame),           DeviceFrame_FADR,      DeviceFrame_LEN,      DeviceFrame_Group,       CA_DeviceFrame},
};

////==============================================================================

/**
 * @brief 对指定长度的数据区域进行校验和计算
 *
 * @param pData 指向数据区域的指针
 * @param len 数据区域的长度
 * @return u8 返回校验和结果
 */
u8 AT45DBDataCheck(volatile u8* pData, u16 len)
{
    u8 result;   // 校验和变量
    result = *pData;   // 初始化为第一个字节的值
    while(len--)
    {
        result += *pData++;   // 累加每个字节的值
    }
    return result;   // 返回校验和结果
}

/****************************************************
函数名：AT45DB_SendByte
功能  ：Flash存储部分用到的SPI发送函数
参数  ：dt 要发送的数据
返回值：无
****************************************************/
u8 AT45DB_SendByte(u8 dt)
{
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI1, dt);
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_I2S_ReceiveData(SPI1);
}

//F*****************************************************************************
//* NAME: ReadDFStatus
//*-----------------------------------------------------------------------------
//* PURPOSE: 
//* 读取45db状态
//*-----------------------------------------------------------------------------
//* PARAMS:
//* return:	如果返回值等0,说明驱动器错误
//*-----------------------------------------------------------------------------
//* NOTE:
//******************************************************************************
u8 ReadDFStatus (void)
{
	u8 result;
	CLI();
	AT45DB_CS_EN;
	AT45DB_SendByte(0xd7);
	result = AT45DB_SendByte(0xff);//要读两次，不然要加10ms延时，暂时不知道为什么
	//delay_ms(10); 
	AT45DB_CS_DIS;
	SEI();
	return	result;
}
//F*****************************************************************************
//* NAME: ReadDriverID
//*-----------------------------------------------------------------------------
//* PURPOSE: 
//* 读取45dbID 判断存储器类型
//*-----------------------------------------------------------------------------
//* PARAMS:
//* return:	Drive ID(Byte 1)Family Code      Density Code
//                            0 0 1((AT45D)  0 0 1 0 0   (4-Mbit)
//                            0 0 1((AT45D)  0 0 1 1 1   (32-Mbit)
//*-----------------------------------------------------------------------------
//* NOTE:
//******************************************************************************
u16 ii = 0;
u8 resultF = 0;
u8 ReadDriverID (void)
{
	CLI();
	for(ii = 0;ii < 200;ii ++)
	{
	  if(ReadDFStatus() & 0x80)
			break;
		delay_ms(1);
	}
	if(ii < 200)
	{
		AT45DB_CS_EN;
		AT45DB_SendByte(0x9F);
		AT45DB_SendByte(0xFF);
		resultF = AT45DB_SendByte(0xFF);
		AT45DB_CS_DIS;
		SEI();
		return resultF;
		}
	SEI();
	return 0;	 
}
u8 AT45DB_SetPageByte (void)
{
	CLI();
	for(ii = 0;ii < 200;ii ++)
	{
	  if(ReadDFStatus() & 0x80)
			break;
		delay_ms(1);
	}
	if(ii < 200)
	{
		AT45DB_CS_EN;
		AT45DB_SendByte(0x3D);
		AT45DB_SendByte(0x2A);
		AT45DB_SendByte(0x80);
		AT45DB_SendByte(0xA7);//A6:512;A7:528
		AT45DB_CS_DIS;
		SEI();
		return 1;
		}
	SEI();
	return 0;	 
}
u8 AT45DB_WriteBuff(u8 *Buff,u16 Len)
{
  u16 i = 0;
	CLI();
	for(ii = 0;ii < 200;ii ++)
	{
	  if(ReadDFStatus() & 0x80)
			break;
		delay_ms(1);
	}
	if(ii < 200)
	{
		AT45DB_CS_EN;
	  AT45DB_SendByte(0x84);
		AT45DB_SendByte(0x00);
		AT45DB_SendByte(0x00);
		AT45DB_SendByte(0x00);
		for(i = 0;i < Len;i ++)
		  AT45DB_SendByte(*(Buff + i));
		AT45DB_CS_DIS;
		SEI();
		return 1;
	  }
	SEI();
	return 0;	
}  

u8 AT45DB_WritePage(u8 *Buff,u16 Page,u16 Len)//len = 10,79us
{
	CLI();
	if(AT45DB_WriteBuff(Buff,Len) == 0)
		return 0;
	for(ii = 0;ii < 200;ii ++)
	{
	  if(ReadDFStatus() & 0x80)
			break;
		delay_ms(1);
	}
	if(ii < 200)
	{
		AT45DB_CS_EN;
	  AT45DB_SendByte(0x83);
		AT45DB_SendByte((u8)(Page >> 6));
		AT45DB_SendByte((u8)(Page << 2));
		AT45DB_SendByte(0x00);
		AT45DB_CS_DIS;
		
		SEI();
		return 1;
	  }
	SEI();
	return 0;	
}

u8 AT45DB_ReadPage(u8 *Buff,u16 Page,u16 Len)//len = 10,75us
{
  u16 i = 0;
	CLI();
	for(ii = 0;ii < 200;ii ++)
	{
	  if(ReadDFStatus() & 0x80)
			break;
		delay_ms(1);
	}
	if(ii < 200)
	{
		AT45DB_CS_EN;
	  AT45DB_SendByte(0xE8);
		AT45DB_SendByte((u8)(Page >> 6));
		AT45DB_SendByte((u8)(Page << 2));
		AT45DB_SendByte(0x00);
		for(i = 0;i < 4;i ++)
		  AT45DB_SendByte(0x00);
		for(i = 0;i < Len;i ++)
		  *(Buff + i) = AT45DB_SendByte(0xff);
		AT45DB_CS_DIS;
		SEI();
		return 1;
	  }
	SEI();
	return 0;	
}
void AT45DB_Data_Init(void)
{
	volatile u16 i = 0,j = 0,Item = 0;
	u8 Temp_Buff[660];
	u8 Temp = 0;
	for(Item = 0;Item< FramItemEnd;Item ++)
		{
			for(i = 0;i < AT45DBTab[Item].Group;i ++)
			{
				for(j = 0;j < AT45DBTab[Item].len - checkLen_1;j ++)
					Temp_Buff[j] = *(AT45DBTab[Item].upData + j) = *(AT45DBTab[Item].pInitData+j);
				Temp_Buff[AT45DBTab[Item].len - checkLen_1] = AT45DBDataCheck(Temp_Buff,AT45DBTab[Item].len - checkLen_1);
				AT45DB_WritePage(Temp_Buff,AT45DBTab[Item].firstAdr + i,AT45DBTab[Item].len);
			 }
		 }
//		__set_FAULTMASK(1);
//		NVIC_SystemReset();
  }
u8	AT45DBItemWrite(AT45DBItem Type, u16 Group)
{
	u16 i = 0,j = 0,k = 0;
	u8 Temp_Buff[660];
	u8 Temp = 0;
	if(Group >= AT45DBTab[Type].Group)
	  return 0;
	for(i = 0;i < AT45DBTab[Type].len - checkLen_1;i ++)
	{
		*(AT45DBTab[Type].upData + i) = *(AT45DBTab[Type].pData + i);
		Temp_Buff[i] = *(AT45DBTab[Type].upData + i);
	 }
	Temp_Buff[AT45DBTab[Type].len - checkLen_1] = AT45DBDataCheck(Temp_Buff,AT45DBTab[Type].len - checkLen_1);
	for(j = 0;j < 6;j ++)
	{
		AT45DB_WritePage(Temp_Buff,AT45DBTab[Type].firstAdr + Group,AT45DBTab[Type].len);
		
		if(AT45DBItemRead(Type,Group) == 1)
		{
				return 1;
			}
		delay_ms(100);
		}
	// TXHData.ErrState.Flag.e_errFlashParameter = 1;
	return 0;
}
u8 CRCTemp = 0;
u8	AT45DBItemRead(AT45DBItem Type, u16 Group)
{
	volatile  u16 i = 0,j = 0;
	u8 Temp_Buff[660];
	u8 Temp_Buff1[660];
	
	u8 CRCTemp1 = 0;
	
	if(Group >= AT45DBTab[Type].Group)
	  return 0;
	for(j = 0;j < 6;j ++)
	{
		AT45DB_ReadPage(FuniGlobal.Global,AT45DBTab[Type].firstAdr + Group,AT45DBTab[Type].len);
		for(i = 0;i < AT45DBTab[Type].len;i ++)
			*(Temp_Buff+i) = *(AT45DBTab[Type].upData+i);
		CRCTemp = AT45DBDataCheck(Temp_Buff,AT45DBTab[Type].len - checkLen_1);
		if(CRCTemp == Temp_Buff[AT45DBTab[Type].len - checkLen_1])
		{
			for(i = 0;i < AT45DBTab[Type].len - checkLen_1;i ++)
				*(AT45DBTab[Type].pData+i) = *(AT45DBTab[Type].upData+i);
			return 1;
			}
		delay_ms(100);
	}
	// pGun.ErrState.Flag.e_errFlashParameter = 1;
	return 0;
}
u8 ExChangeByte(u8 data)
{
  u8 Temp = 0;
	Temp = data;
	data = (Temp >> 4) | (Temp << 4);
	return data;
}
u8 NotByte(u8 data)
{
  if(data == 0 || data == 0xff)
		return data;
	else
		return ~data;
}

void AT45DB_Init(void)
{
  volatile	u16 Frame = 0;
	u8* pBuff;
	u8 Temp_Buff[660];
	FlashType = ReadDriverID();
	AT45DB_SetPageByte();
	switch(FlashType)
	{
	  case 0x24: TXHData.ATDB45Type = At45DB041;break;
		case 0x27: TXHData.ATDB45Type = At45DB321;break;
		case 0x28: TXHData.ATDB45Type = At45DB641;break;
	  }
//	if(SWF8 == SWF_ON)
//	{
//		if(TXHData.ATDB45Type >= At45DB321)
//		{
//			for(Frame = 0;Frame < 1024;Frame ++)
//			{
//				ReadFlashNx512Btye(&TXHData.Frame[0],FLASH_APP_ADDR + Frame *512);
//				switch(Frame%8)
//				{
//					case 0:TXHData.Frame[2]   =  ExChangeByte(TXHData.Frame[2]);
//								 TXHData.Frame[54]  =  NotByte(TXHData.Frame[54]);
//								 TXHData.Frame[288] =  ExChangeByte(TXHData.Frame[288]);GPIO_SetBits(GPIOE,GPIO_Pin_2);break;
//					case 1:TXHData.Frame[469] =  NotByte(TXHData.Frame[469]);break;
//					case 2:TXHData.Frame[104] =  ExChangeByte(TXHData.Frame[104]);break;
//					case 3:break;
//					case 4:TXHData.Frame[0]   =  NotByte(TXHData.Frame[0]);break;
//					case 5:TXHData.Frame[253] =  ExChangeByte(TXHData.Frame[253]);GPIO_ResetBits(GPIOE,GPIO_Pin_2);break;
//					}
//				AT45DBItemWrite(CA_Frame,Frame + (TXHData.ROM_UpData.ROM_UpData_State.RomAddrNow * 1024));
//			}
//		}
//	}
}
