#ifndef EEPROM_EMULATION_H_
#define EEPROM_EMULATION_H_

#define PAGE_SIZE  (512u)
#define MIN_ERASE_SIZE (PAGE_SIZE*16u)
#define BLOCK_SIZE (MIN_ERASE_SIZE)
#define SECTOR_SIZE (PAGE_SIZE*256u)
#define FLASH_START (0x00400000u)
#define FLASH_SIZE  (0x00080000u) // 512kB of Flash
#define EEPROM_BLOCK0_START  (FLASH_START + FLASH_SIZE - 2*(MIN_ERASE_SIZE))
#define EEPROM_BLOCK0_START_PAGE ((EEPROM_BLOCK0_START - FLASH_START)/PAGE_SIZE)
#define EEPROM_BLOCK1_START  (EEPROM_BLOCK0_START + MIN_ERASE_SIZE)
#define EEPROM_BLOCK1_START_PAGE ((EEPROM_BLOCK1_START - FLASH_START)/PAGE_SIZE)

#define FLASH_ERASED_32B    (0xFFFFFFFFu)
#define FLASH_TAGGED_32B    (0x33333333u)

#define EEPROM_VARIABLE_SIZE    (8u) // 8 bytes for each variable, 4 for tag, 4 for data
#define EEPROM_TAG_OFFSET       (0u)
#define EEPROM_DATA_OFFSET      (4u)

typedef enum _EEPROM_Status {
    EEPROM_Erased, 
    EEPROM_Transferring, // Currently moving data from other page to this one
    EEPROM_Active, // This is the active page, any new data is written here
    EEPROM_Invalid 
} EEPROM_Status_T;

typedef enum _EEPROM_Read_Status {
    EEPROM_Found,
    EEPROM_Not_Found,
    EEPROM_Read_Error,
	EEPROM_Read_Not_Init
} EEPROM_Read_Status_T;

typedef enum _EEPROM_Write_Status {
    EEPROM_Write_Success,
    EEPROM_Full,
    EEPROM_Write_Error,
	EEPROM_Write_Not_Init
} EEPROM_Write_Status_T;

typedef enum _EEPROM_Operation {
    EEPROM_Write_Operation,
    EEPROM_Read_Operation
} EEPROM_Operation_T;

typedef enum _EEPROM_Block {
    EEPROM_Block0,
    EEPROM_Block1,
    EEPROM_No_Block
} EEPROM_Block_T;

typedef enum _EEPROM_Keys {
    EEKEY_TotalPoweredOnTime10min = 0xFFFF1001,
    EEKEY_TotalDisplaysOnTime10min_Left = 0xFFFF1002,
    EEKEY_LongestDisplaysOnTime10min = 0xFFFF1003,
	EEKEY_TotalDisplaysOnTime10min_Right = 0xFFFF1004,
    EEKEY_NumTimesBlock0Erased = 0xFFFF2001,
    EEKEY_NumTimesBlock1Erased = 0xFFFF2002,
	EEKEY_None = 0xFFFFFFFF
} EEPROM_Keys_T;

uint32_t EEPROM_Init(void);
EEPROM_Read_Status_T EEPROM_Read(uint32_t key, uint32_t* data);
EEPROM_Write_Status_T EEPROM_Write(uint32_t key, uint32_t data);
EEPROM_Block_T EEPROM_Which_Block_Active(void);

#endif 
