#ifndef _EEPROM_24CXX_H_
#define _EEPROM_24CXX_H_

#include "r_typedefs.h"
#include "RTE_GPIO.h"

#define   EEPROM_24C16

#define   EEPROM_WP_ENABLE                  0

#if       EEPROM_WP_ENABLE  
  #ifndef     EEPROM_WP
    #define   EEPROM_WP
  #endif
#endif

#define   EEPROM_BUFFER_SIZE                32


#define   EEPROM_DEVICE_ADDR_WR             0xA0
#define   EEPROM_DEVICE_ADDR_RD             0xA1

#if   defined EEPROM_24C01                  
  #define EEPROM_DATA_ADDR_1_BYTE
  #define EEPROM_MAX_DATA_ADDR              0x007F
  #define EEPROM_TOTAL_PAGE_NUM             16
  #define EEPROM_PAGE_SIZE                  8
  
#elif defined EEPROM_24C02                
  #define EEPROM_DATA_ADDR_1_BYTE
  #define EEPROM_MAX_DATA_ADDR              0x00FF
  #define EEPROM_TOTAL_PAGE_NUM             32
  #define EEPROM_PAGE_SIZE                  8
  
#elif defined EEPROM_24C04                
  #define EEPROM_DATA_ADDR_2_BYTE_MIXED
  #define EEPROM_MAX_DATA_ADDR              0x01FF
  #define EEPROM_TOTAL_PAGE_NUM             32
  #define EEPROM_PAGE_SIZE                  16
  
#elif defined EEPROM_24C08                 
  #define EEPROM_DATA_ADDR_2_BYTE_MIXED
  #define EEPROM_MAX_DATA_ADDR              0x03FF
  #define EEPROM_TOTAL_PAGE_NUM             64
  #define EEPROM_PAGE_SIZE                  16
  
#elif defined EEPROM_24C16                
  #define EEPROM_DATA_ADDR_2_BYTE_MIXED
  #define EEPROM_MAX_DATA_ADDR              0x07FF
  #define EEPROM_TOTAL_PAGE_NUM             128
  #define EEPROM_PAGE_SIZE                  16

#elif defined EEPROM_24C32                 
  #define EEPROM_DATA_ADDR_2_BYTE
  #define EEPROM_MAX_DATA_ADDR              0x0FFF
  #define EEPROM_TOTAL_PAGE_NUM             128
  #define EEPROM_PAGE_SIZE                  32

#elif defined EEPROM_24C64                  
  #define EEPROM_DATA_ADDR_2_BYTE
  #define EEPROM_MAX_DATA_ADDR              0x1FFF
  #define EEPROM_TOTAL_PAGE_NUM             256
  #define EEPROM_PAGE_SIZE                  32

#elif defined EEPROM_24C128                 
  #define EEPROM_DATA_ADDR_2_BYTE
  #define EEPROM_MAX_DATA_ADDR              0x3FFF
  #define EEPROM_TOTAL_PAGE_NUM             256
  #define EEPROM_PAGE_SIZE                  64
  
#elif defined EEPROM_24C256                 
  #define EEPROM_DATA_ADDR_2_BYTE
  #define EEPROM_MAX_DATA_ADDR              0x7FFF
  #define EEPROM_TOTAL_PAGE_NUM             512
  #define EEPROM_PAGE_SIZE                  64
  
#elif defined EEPROM_24C512                 
  #define EEPROM_DATA_ADDR_2_BYTE
  #define EEPROM_MAX_DATA_ADDR              0xFFFF
  #define EEPROM_TOTAL_PAGE_NUM             512
  #define EEPROM_PAGE_SIZE                  128
    
#else                                       
  #error  EEPROM device is undefined
  
#endif


#define   EEPROM_IDLE                       0x00
#define   EEPROM_WR                         0x10
#define   EEPROM_RD                         0x20

#define   EEPROM_WR_START                   0x10
#define   EEPROM_WR_ADDR                    0x11
#define   EEPROM_WR_DATA                    0x12
#define   EEPROM_WR_STOP                    0x13

#define   EEPROM_RD_START                   0x20
#define   EEPROM_RD_ADDR1                   0x21
#define   EEPROM_RD_RESTART                 0x22
#define   EEPROM_RD_ADDR2                   0x23
#define   EEPROM_RD_DATA                    0x24
#define   EEPROM_RD_STOP                    0x25

typedef enum
{
  EEPROM_OK = 0,                       
  EEPROM_BUSY,                         
  EEPROM_INVALID_DEVICE_ADDR,          
  EEPROM_INVALID_DATA_ADDR,            
  EEPROM_DATA_LENGTH_ERR,              
  EEPROM_NO_RESPONSE,                  
}EEPROMErrEnum;


typedef enum
{
  EEPROM_RW_IDLE = 0,                  
  EEPROM_RW_REQ,                       
  EEPROM_RW_BUSY,                      
}EEPROMRWStateEnum;


typedef enum
{
  EEPROM_RW_NONE = 0,                  
  EEPROM_RW_DONE,                      
  EEPROM_RW_FAIL,                      
  EEPROM_RW_IN_PROGRESS,               
}EEPROMRWResultEnum;


typedef struct
{
  uint8_t             State;
  uint8_t             Cnt;
  uint8_t             WRAddrLen;
  uint8_t             WRAddr[3];
  uint8_t             WRDataLen;
  uint8_t             WRData[EEPROM_BUFFER_SIZE];
  EEPROMRWStateEnum   WRState;
  EEPROMRWResultEnum  WRResult;
  uint8_t             RDAddrLen;
  uint8_t             RDAddr[3];
  uint8_t             RDDataLen;
  uint8_t             RDData[EEPROM_BUFFER_SIZE];
  EEPROMRWStateEnum   RDState;
  EEPROMRWResultEnum  RDResult;
}EEPROMRWStruct;

extern EEPROMRWStruct  EEPROMRW;



EEPROMErrEnum EEPROM_Instant_Byte_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t Data);
EEPROMErrEnum EEPROM_Instant_Page_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len);
EEPROMErrEnum EEPROM_Instant_Page_Write_Repeatedly(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len);
EEPROMErrEnum EEPROM_Byte_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t Data);
EEPROMErrEnum EEPROM_Page_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len);
EEPROMRWResultEnum EEPROM_Get_Write_Result(void);
void EEPROM_Write_In(void);

EEPROMErrEnum EEPROM_Instant_Byte_Read(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData);
EEPROMErrEnum EEPROM_Instant_Sequential_Read(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len);
EEPROMErrEnum EEPROM_Byte_Read(uint8_t DeviceAddr, uint16_t DataAddr);
EEPROMErrEnum EEPROM_Sequential_Read(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t Len);
EEPROMRWResultEnum EEPROM_Get_Read_Result(void);
uint8_t EEPROM_Get_Read_Out_Byte(void);
void EEPROM_Get_Read_Out(uint8_t *pData, uint8_t Len);
void EEPROM_Read_Out(void);

void EEPROM_Init(void);
void EEPROM_RW_Service(void);

#endif