#include "Non_volatile_Memorys.h"


uint8_t NVMEEPROMFault;

NVMInitUnion          NVMInit;
NVMODOUnion           NVMODO;
NVMUserSettingsUnion  NVMUserSettings;
//NVMConfigF110Union    NVMConfigF110;
//NVMConfigF101Union    NVMConfigF101;
NVMDTCUnion           NVMDTC;
NVMConfig3300Union    NVMConfig3300;
NVMUpdateCtrlStruct   NVMUpdateCtrl;
uint8_t NVMDiesel;
NVMConfigF184Union   NVMConfigF184;
NVMConfigF1A8Union   NVMConfigF1A8;
NVMConfigF190Union   NVMConfigF190;
NVMRESETODOUnion  NVMRESETODO;
void NVM_Init(void)
{
  uint8_t   i;
  uint8_t   j;

  uint8_t   *pData;
  uint8_t   *pDefaultValue;
  uint8_t   Len;

#if NVM_USE_EEPROM

  uint8_t   Type;
  uint16_t  Addr;

  uint8_t   InitStatus;
  EEPROMAccessStatusEnum    Status;

  //��ʼ�����¿���
  NVMUpdateCtrl.Enable  = 0;
  NVMUpdateCtrl.Current = 0xFF;              //0xFF = ��Ч�ź�
  for (i = 0; i < NVM_TOTAL_DATA_NUM; i++)
    NVMUpdateCtrl.Req[i] = 0;

  //���EEPROM���޳�ʼ����
  pData  = NVMDataAttributeTable[NVM_INIT_DATA].pData;
  Len    = NVMDataAttributeTable[NVM_INIT_DATA].Len;
  Type   = NVMDataAttributeTable[NVM_INIT_DATA].DataType;
  Addr   = NVMDataAttributeTable[NVM_INIT_DATA].Addr;

  //��ȡ��ʼ����־
  Status = EEPROM_Startup_Data_Read(Type, Addr, pData, Len);

  //���ݶ�ȡ״̬�жϳ�ʼ��״̬
  if (Status == EEPROM_DATA_OK)
  {
    NVM_EEPROM_FAULT = 0;
    InitStatus       = 1;
  }
  else if (Status == EEPROM_DATA_PARTIAL_LOST)
  {
    NVM_EEPROM_FAULT = 0;
    InitStatus       = 1;
    NVM_Data_Update(NVM_INIT_DATA);
  }
  else if (Status == EEPROM_DATA_LOST)
  {
    NVM_EEPROM_FAULT = 0;
    InitStatus       = 0;
  }
  else
  {
    NVM_EEPROM_FAULT = 1;
    InitStatus       = 0;
  }

  //�ȶԳ�ʼ����־
  if (InitStatus)
  {
    i = 0;
    pDefaultValue = NVMDataAttributeTable[NVM_INIT_DATA].pDefaultValue;

    while (i < Len)
    {
      if (pData[i] != pDefaultValue[i])
      {
        InitStatus = 0;
        break;
      }
      i++;
    }
  }

  if (InitStatus)                                 //�洢���ѳ�ʼ����,��Ӵ洢���ж�ȡ����
  {
#pragma MESSAGE DISABLE C4000
    if (NVM_TOTAL_DATA_NUM > 1)
    {
      for (i = 1; i < NVM_TOTAL_DATA_NUM; i++)
      {
        pData  = NVMDataAttributeTable[i].pData;
        Len    = NVMDataAttributeTable[i].Len;
        Type   = NVMDataAttributeTable[i].DataType;
        Addr   = NVMDataAttributeTable[i].Addr;

        //��ȡ����
        Status = EEPROM_Startup_Data_Read(Type, Addr, pData, Len);

        if (Status == EEPROM_DATA_PARTIAL_LOST)   //���ݲ��ֶ�ʧ,ʹ�ö���������,�����¸��´洢��
        {
          NVM_Data_Update(i);
        }
        else if (Status != EEPROM_DATA_OK)        //����û�б��ɹ�����,ʹ��Ĭ��ֵ,�����´洢��
        {
          pDefaultValue = NVMDataAttributeTable[i].pDefaultValue;

          for (j = 0; j < Len; j++)
            pData[j] = pDefaultValue[j];

          NVM_Data_Update(i);
        }
      }
    }
  }
  else                                            //�洢��δ��ʼ����,��ʹ������Ĭ��ֵ,��������µ��洢��
  {
    for (i = 0; i < NVM_TOTAL_DATA_NUM; i++)
    {
      pData         = NVMDataAttributeTable[i].pData;
      pDefaultValue = NVMDataAttributeTable[i].pDefaultValue;
      Len           = NVMDataAttributeTable[i].Len;

      for (j = 0; j < Len; j++)
        pData[j] = pDefaultValue[j];

      NVM_Data_Update(i);
    }
  }

#else                                             

  NVM_EEPROM_FAULT = 0;

  for (i = 0; i < NVM_TOTAL_DATA_NUM; i++)
  {
    pData         = NVMDataAttributeTable[i].pData;
    pDefaultValue = NVMDataAttributeTable[i].pDefaultValue;
    Len           = NVMDataAttributeTable[i].Len;

    for (j = 0; j < Len; j++)
      pData[j] = pDefaultValue[j];
  }

#endif
}

void NVM_Data_Update(uint8_t DataName)
{
#if NVM_USE_EEPROM

  if (NVM_EEPROM_FAULT == 0)                //����洢��δ��������
  {
    if (DataName < NVM_TOTAL_DATA_NUM)
    {
      NVMUpdateCtrl.Req[DataName] = 1;
      NVMUpdateCtrl.Enable = 1;
    }
  }

#endif
}


void NVM_Data_Update_Service(void)
{
#if NVM_USE_EEPROM

  uint8_t   i;

  uint8_t   *pData;
  uint8_t   Len;
  uint8_t   Type;
  uint16_t  Addr;

  EEPROMAccessStatusEnum Status;

  if (NVMUpdateCtrl.Enable)
  {
    if (NVMUpdateCtrl.Current < NVM_TOTAL_DATA_NUM)   //������������ݴ洢
    {
      Status = EEPROM_Get_Data_Write_Status();

      if (Status == EEPROM_DATA_OK)                   //���ݳɹ�д��,���д������
        NVMUpdateCtrl.Req[NVMUpdateCtrl.Current] = 0;
      else if (Status == EEPROM_MEMORY_BUSY)          //��������д����,ֱ�ӷ���
        return;
    }

    NVMUpdateCtrl.Current = 0xFF;

    //������Ҫ���µ�����,�ڸ������������ݺ�Ÿ��³�ʼ������
    i = NVM_TOTAL_DATA_NUM;

    while (i)
    {
      i--;

      if (NVMUpdateCtrl.Req[i])
      {
        pData  = NVMDataAttributeTable[i].pData;
        Len    = NVMDataAttributeTable[i].Len;
        Type   = NVMDataAttributeTable[i].DataType;
        Addr   = NVMDataAttributeTable[i].Addr;

        Status = EEPROM_Data_Write(Type, Addr, pData, Len);

        if (Status == EEPROM_DATA_OK)
          NVMUpdateCtrl.Current = i;

        return;
      }
    }

    NVMUpdateCtrl.Enable  = 0;
  }
#endif
}