#ifndef _BSP_EEPROM_H_
#define _BSP_EEPROM_H_

#ifdef   __cplusplus
extern   "C" {
#endif

#include "drv_flash.h"
  

/*****************************MCU eeprom配置*****************************/
#define BSP_EEPROM_REWRITE_CNT          3

#define BSP_EEPROM_AREA_BIT_MASK        0x03
#define BSP_EEPROM_AREA_NONE            0x00
#define BSP_EEPROM_AREA_DYNAMIC         0x01
#define BSP_EEPROM_AREA_STATIC          0x02

#define BSP_EEPROM_CHECK_MAX_MIN_BIT_MASK       0x04
#define BSP_EEPROM_CHECK_MAX_MIN_OFF            0x00
#define BSP_EEPROM_CHECK_MAX_MIN_ON             0x04

#define BSP_EEPROM_CHECK_EQUAL_BIT_MASK         0x08
#define BSP_EEPROM_CHECK_EQUAL_OFF              0x00
#define BSP_EEPROM_CHECK_EQUAL_ON               0x08

#define NONE_CHECK                      (BSP_EEPROM_AREA_NONE | BSP_EEPROM_CHECK_MAX_MIN_ON)
#define STATIC_CHECK                    (BSP_EEPROM_AREA_STATIC | BSP_EEPROM_CHECK_MAX_MIN_ON  | BSP_EEPROM_CHECK_EQUAL_ON)
#define STATIC_UNCHECK_MAX_MIN          (BSP_EEPROM_AREA_STATIC | BSP_EEPROM_CHECK_MAX_MIN_OFF | BSP_EEPROM_CHECK_EQUAL_ON)
#define STATIC_UNCHECK_ALL              (BSP_EEPROM_AREA_STATIC | BSP_EEPROM_CHECK_MAX_MIN_OFF | BSP_EEPROM_CHECK_EQUAL_OFF)
#define DAYNMIC_CHECK                   (BSP_EEPROM_AREA_DYNAMIC | BSP_EEPROM_CHECK_MAX_MIN_ON | BSP_EEPROM_CHECK_EQUAL_ON)
#define DAYNMIC_UNCHECK_MAX_MIN         (BSP_EEPROM_AREA_DYNAMIC | BSP_EEPROM_CHECK_MAX_MIN_OFF | BSP_EEPROM_CHECK_EQUAL_ON)
#define DAYNMIC_UNCHECK_ALL             (BSP_EEPROM_AREA_DYNAMIC | BSP_EEPROM_CHECK_MAX_MIN_OFF| BSP_EEPROM_CHECK_EQUAL_OFF)

#define PARAM_CONVERT(v, fac, off)      (((v)+(off))*(fac))
#define PARAM_COMBINE(high, low)        (((uint16_t)((uint16_t)high) << 8) | ((uint8_t)(low)))

typedef enum 
{
    kEepromDataType_Low = 0,
    kEepromDataType_High = 1,
    kEepromDataType_Full = 2,
    kEepromDataType_Double = 4,
    kEepromDataType_End,
}EepromDataType;


typedef union
{
    uint32_t value;
    struct
    {
        uint16_t value;
        uint16_t idx;
    }item;
}EepromPoData;




typedef struct
{
    uint8_t  property;
    uint16_t config_default;
    uint16_t config_min;
    uint16_t config_max;        
}EepromDataFormat;

typedef struct
{
    uint8_t  type;
    uint8_t  erase_page_num;
    uint16_t area_size;
    uint16_t data_cnt;
    uint32_t main_addr;
    uint32_t sub_addr;
    uint32_t write_addr;
}AreaItem;

typedef struct 
{
    uint8_t  backup_area_page_num;
    uint16_t total_data_cnt;
    uint32_t check_addr_offset;
    uint32_t backup_area_addr;
    uint16_t * data_buf;
    const EepromDataFormat * format;
    FlashItem *flash; 
    
    AreaItem static_area;
    AreaItem dynamic_area;
}EEpromItem;


#define EEPROM_STATIC_INIT(_name, _format, _len, _flash)   \
    uint16_t _name##_buf[_len];  \
    EEpromItem _name =   \
    {   \
        0, \
        (_len),    \
        0,  \
        0,  \
        _name##_buf,    \
        _format,    \
        _flash, \
    }

#define EEPROM_STATIC_INIT_CCM(_name, _format, _len, _flash)   \
    uint16_t _name##_buf[_len] __attribute__((section (".CCM_RAM")));  \
    EEpromItem _name =   \
    {   \
        0, \
        (_len),    \
        0,  \
        0,  \
        _name##_buf,    \
        _format,    \
        _flash, \
    }    


bool bsp_eeprom_init(EEpromItem *item, uint8_t backup_page_num, uint8_t static_page_num, uint8_t dynamic_page_num, uint32_t start_addr);
bool bsp_eeprom_set_data(uint16_t idx, uint32_t value, EepromDataType type);
bool bsp_eeprom_save_data(uint16_t idx, uint32_t value, EepromDataType type);
void bsp_eeprom_power_off_save_data(EepromPoData *data, uint32_t len);
bool bsp_eeprom_backup_static_area(void);
bool bsp_eeprom_recovery_static_area(EEpromItem *item, uint16_t except_idx);
uint32_t bsp_eeprom_get_data(uint16_t idx, EepromDataType type);
    
#ifdef   __cplusplus
}
#endif

#endif
