#include "includes.h"
#include "trace.h"
#include "w25qxx.h"
#include "m95512.h"

//==============================================================================
// 描述: 在AT25读状态寄存器
// 输入: 无
// 返回: unsigned char dat 状态寄存器数据
//==============================================================================


/**
  * @brief  SPII/O配置
  * @param  无
  * @retval 无
  */
static void SPI_E2PROM_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure; 

	//初始化CS引脚，使用软件控制，所以直接设置成推挽输出    
	GPIO_InitStructure.GPIO_Pin = E2PROM_SPI_CS_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         
	GPIO_Init(E2PROM_SPI_CS_PORT, &GPIO_InitStructure);

	E2PROM_SPI_CS_HIGH;
}

u8 eeprom_read_sr(void)
{ 
	u8 dat; 
	E2PROM_SPI_CS_LOW; 
	SPI_USER_Send_Byte(RDSR);        //  定入指令0x05
	dat = SPI_USER_Send_Byte(0xff);       //  读回数据
	E2PROM_SPI_CS_HIGH;

	//printf("rdsr = 0x%x\r\n", dat);
	return  dat;
}

//==============================================================================
// 描述: 向AT25写入一个数据
// 输入: unsigned char Dat 字符数据
//       unsigned int addr 写入的地址
// 返回: 无
//==============================================================================
void eeprom_write_byte(u16 addr,u8 Dat)
{ 
	unsigned char Add; 
	while(eeprom_read_sr()&RDY);                   // 读状态寄存器
	
	E2PROM_SPI_CS_LOW;
	SPI_USER_Send_Byte(WREN);                           // 写使能锁存
	E2PROM_SPI_CS_HIGH;
	
	E2PROM_SPI_CS_LOW;                                  // 芯片使能 
	// 写入写操作指令 
	if(addr>0x00ff)
		SPI_USER_Send_Byte((WRITE|0x08));           // 地址大于255
	else
		SPI_USER_Send_Byte(WRITE);                  // 地址小于255

	// 写入地址
	Add = (unsigned char)(addr & 0xff);             // 将地址换成8位
	SPI_USER_Send_Byte(Add); 

	// 写入数据
	SPI_USER_Send_Byte(Dat);
	E2PROM_SPI_CS_HIGH;                                // 芯片关闭    
}
//==============================================================================
// 描述: 在AT25读一个字节操作
// 输入: 无
// 返回: unsigned char dat 读出一个字符数据
//==============================================================================
u8 eeprom_read_byte(u16 addr)
{ 
	u8 dat,add;
	while(eeprom_read_sr()&RDY);                   // 读状态寄存器  
	E2PROM_SPI_CS_LOW;
	// 写入写操作指令 
	if(addr>0x00ff)
		SPI_USER_Send_Byte((READ | 0x08));         // 地址大于255
	else
		SPI_USER_Send_Byte(READ);                  // 地址小于255

	// 写入地址
	add = (unsigned char)(addr & 0xff);             // 将地址换成8位
	SPI_USER_Send_Byte(add); 

	// 读出一个数据
	dat=SPI_USER_Send_Byte(0xff);
	E2PROM_SPI_CS_HIGH;
	return dat;
}
//==============================================================================
// 描述: 向AT25连续写入数据
// 输入: unsigned char *PC 写入数据指针
//       unsigned int count 写入数量计数  
//       unsigned int SatAddr 写入起始地址
// 返回: 无
//==============================================================================
void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count)
{ 
	u8 Add; 
	u16 i;
	while(eeprom_read_sr()&RDY);                   // 读状态寄存器

	E2PROM_SPI_CS_LOW;
	SPI_USER_Send_Byte(WREN);                           // 写使能锁存
	E2PROM_SPI_CS_HIGH;
	E2PROM_SPI_CS_LOW;
	// 写入写操作指令 
	if(startAddr>0x00ff)
		SPI_USER_Send_Byte((WRITE|0x08));           // 地址大于255
	else
		SPI_USER_Send_Byte(WRITE);                  // 地址小于255

	// 写入地址
	Add = (unsigned char)(startAddr & 0xff);             // 将地址换成8位
	SPI_USER_Send_Byte(Add); 

	for(i=0;i<count;i++)// 写入数据
	{ 
		SPI_USER_Send_Byte(*buf++);
	}
	E2PROM_SPI_CS_HIGH;                                 // 芯片关闭    
}
//==============================================================================
// 描述: 在AT25连续读数据
// 输入: unsigned char *PC 读出数据指针
//       unsigned int count 读出数量计数  
//       unsigned int SatAddr 读出起始地址
// 返回: 无
//==============================================================================
void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count)
{ 
	unsigned char Add; 
	unsigned int i;
	while(eeprom_read_sr()&RDY);                   // 读状态寄存器  
	E2PROM_SPI_CS_LOW;
	// 写入写操作指令 
	if(startAddr>0x00ff)
		SPI_USER_Send_Byte((READ | 0x08));         // 地址大于255
	else
		SPI_USER_Send_Byte(READ);                  // 地址小于255

	// 写入地址
	Add = (unsigned char)(startAddr & 0xff);             // 将地址换成8位
	SPI_USER_Send_Byte(Add); 

	// 读出n个数据
	for(i=0;i<count;i++)
	{
		*buf++ = SPI_USER_Send_Byte(0xff);
	}
	E2PROM_SPI_CS_HIGH;
}

//读取FLASH的内容
void SPI_E2PROM_Read_Data(uint32_t addr,uint8_t *readBuff,uint32_t numByteToRead)
{
        //片选使能
    E2PROM_SPI_CS_LOW;
    SPI_USER_Send_Byte(READ);
    SPI_USER_Send_Byte((addr>>8)&0xff); 
  	SPI_USER_Send_Byte(addr&0xff); 
    while(numByteToRead--)
    {   
        *readBuff = SPI_USER_Send_Byte(DUMMY);
        readBuff++;
    }

    E2PROM_SPI_CS_HIGH;  
}

//FLASH写入使能
void SPI_E2PROM_Write_Enable(void)
{
    //片选使能
    E2PROM_SPI_CS_LOW;
    SPI_USER_Send_Byte(WREN);   
    E2PROM_SPI_CS_HIGH;

	//eeprom_read_sr();
	//while((eeprom_read_sr()&RDY) == RDY);                   // 读状态寄存器
}

//FLASH写入使能
void SPI_E2PROM_Write_Disable(void)
{
    //片选使能
    E2PROM_SPI_CS_LOW;
    SPI_USER_Send_Byte(WRDIS);   
    E2PROM_SPI_CS_HIGH;

	//eeprom_read_sr();
	//while((eeprom_read_sr()&RDY) == RDY);                   // 读状态寄存器
}

//向FLASH写入内容
void SPI_E2PROM_Write_Data(uint32_t addr,uint8_t *writeBuff,uint32_t numByteToWrite)
{
    SPI_E2PROM_Write_Enable();
    //eeprom_read_sr();
        //片选使能
    E2PROM_SPI_CS_LOW;
    SPI_USER_Send_Byte(WRITE);
    SPI_USER_Send_Byte((addr>>8)&0xff); 
  	SPI_USER_Send_Byte(addr&0xff); 
    while(numByteToWrite--)
    {   
        SPI_USER_Send_Byte(*writeBuff);
        writeBuff++;
    }
	
    E2PROM_SPI_CS_HIGH;  
	SPI_E2PROM_Write_Disable();
}
static u8 Spi_E2_Buf_Write[256], Spi_E2_Buf_Read[256];
uint8_t SPI_E2PROM_Test(void)
{
	u16 i;

	SPI_USER_Init();
	SPI_E2PROM_GPIO_Config();
		
	//id = SPI_FLASH_Read_ID();
	if(1) {
		memset(Spi_E2_Buf_Write, 0, 256);
		for ( i=0; i<=255; i++ ) {//填充缓冲
			Spi_E2_Buf_Write[i] = i+20;
		}
		data_dump("E2PROM Write", Spi_E2_Buf_Write, sizeof(Spi_E2_Buf_Write));
		//字节写入方式
		SPI_E2PROM_Write_Data(0, Spi_E2_Buf_Write, 128);
		delay_ms(1000);
		//将 EEPROM 读出数据顺序保持到 I2c_Buf_Read 中
		memset(Spi_E2_Buf_Read, 0, 256);
		SPI_E2PROM_Read_Data(0, Spi_E2_Buf_Read, 128);
		//将 I2c_Buf_Read 中的数据通过串口打印		
		data_dump("E2PROM Read", Spi_E2_Buf_Read, sizeof(Spi_E2_Buf_Read));
		printf("\r\nSPI(m95512)rw success\r\n");
		delay_ms(1000);
	}

	return 1;
}
