/* 
* classW25Qflash.h
*
* Created: 02/03/2015 15:12:19
* Author: Vaio
*/


#ifndef __CLASSW25QFLASH_H__
#define __CLASSW25QFLASH_H__

#include "classSPI.h"
#include "classPio.h"
#include "asf.h"

#define W25P_WriteEnable 0x06
#define W25P_WriteDisable 0x04
#define W25P_ReadStatusReg 0x05
#define W25P_WriteStatusReg 0x01
#define W25P_ReadData  0x03
#define W25P_FastReadData 0x0B
#define W25P_PageProgram 0x02
#define W25P_SectorErase 0x20 // 4KB
#define W25P_32K_BlockErase 0x52 // 32KB
#define W25P_64K_BlockErase 0xD8 // 64KB
#define W25P_ChipErase  0xC7
#define W25P_PowerDown  0xB9
#define W25P_ReleasePowerDown 0xAB
#define W25P_DeviceID  0xAB
#define W25P_ManufactDeviceID 0x90
#define R_JEDEC_ID	0x9f	//read JEDEC ID = Manuf+ID (suggested)

//Memoria Flash serie Winbond
#define WB_P_PIN                PIO_PA11_IDX
#define WB_P_PIN_MASK           (1<<11)
#define WB_CS_PIN               PIO_PA10_IDX
#define WB_CS_PIN_MASK          (1<<10)


  enum partNumber : uint8_t
  {
	  W25Q80 = 1,
	  W25Q16 = 2,
	  W25Q32 = 4,
	  W25Q64 = 8,
	  W25Q128 = 16
  };


typedef struct 
{
	partNumber pn;
	uint16_t id;
	uint32_t bytes;
	uint32_t pages;
	uint16_t sectors;
	uint16_t blocks;
}pnListType;

static const pnListType pnList[] = 
{
	{ W25Q80, 0x4014,1048576, 4096, 256, 16  },
	{ W25Q16, 0x4015,2097152, 8192, 512, 32  },
	{ W25Q32, 0x4016,4194304, 16384,1024,64  },
	{ W25Q64, 0x4017,8388608, 32768,2048,128 },
	{ W25Q128,0x4018,16777216,65536,4096,256 }
};


extern classSpi Spi0;
extern classPio Puerto;
class classW25Qflash
{
//variables
public:
    uint8_t tx_buff[2];
	union
	{
		uint8_t  temp_buffer[512];
		uint16_t  temp16_buffer[256];
	}u;
protected:
private:

//functions
public:
	classW25Qflash();
	void IO_Send_Byte(uint8_t out);
	uint8_t IO_Get_Byte();
	void IO_Wait_Busy();
	uint8_t IO_Read_StatusReg();  //Reads the status register of the serial flash
	void IO_Write_StatusReg(uint8_t byte);//Performs a write to the status register
	void IO_Write_Enable();	//Write enables the serial flash
	void IO_PowerDown();
	void IO_ReleasePowerDown();
	uint8_t IO_Read_ID1();//Reads the device ID using the instruction 0xAB
	uint16_t IO_Read_ID2(uint8_t ID_Addr);//Reads the manufacturer ID and device ID with 0x90
	uint8_t IO_Read_Byte(unsigned long Dst_Addr);//Reads one byte from the serial flash and returns byte(max of 40 MHz CLK frequency)
	void IO_Read_nBytes(unsigned long Dst_Addr, uint16_t nBytes_128);//Reads multiple bytes(max of 40 MHz CLK frequency)
	uint16_t IO_Read_word(unsigned long Dst_Addr);
	uint8_t IO_FastRead_Byte(unsigned long Dst_Addr);//Reads one byte from the serial flash and returns byte(max of 80 MHz CLK frequency)
	void IO_FastRead_nBytes(unsigned long Dst_Addr, uint16_t nBytes_128);//Reads multiple bytes(max of 80 MHz CLK frequency)
	void IO_Write_Byte(unsigned long Dst_Addr, uint8_t byte);//Program one byte to the serial flash
	void IO_Write_nBytes(unsigned long Dst_Addr, uint16_t nBytes_128);//Program n bytes to the serial flash, n<=256
	void IO_Erase_Chip();//Erases entire serial flash
	void IO_Erase_Sector(unsigned long Dst_Addr);//Erases one sector (4 KB) of the serial flash
	void IO_Erase_Block32(unsigned long Dst_Addr);//Erases block (32 KB) of the serial flash
	void IO_Erase_Block64(unsigned long Dst_Addr);//Erases block (64 KB) of the serial flash

	void Verify(uint8_t byte, uint8_t cor_byte);
	void IO_Write_Disable();//Write disables the serial flash
	uint16_t IO_Read_ID3();
	~classW25Qflash();
protected:
private:
	classW25Qflash( const classW25Qflash &c );
	classW25Qflash& operator=( const classW25Qflash &c );
	#define chip_select()     {PIOA->PIO_CODR = 1 << (WB_CS_PIN & 0x1F);}
	#define chip_deselect()   {PIOA->PIO_SODR = 1 << (WB_CS_PIN & 0x1F);}
    #define chip_protect()    {Puerto.set_pin_low(PIOD,WB_P_PIN);}
    #define chip_unprotect()  {Puerto.set_pin_high(PIOD,WB_P_PIN);}


}; //classW25Qflash

#endif //__CLASSW25QFLASH_H__
