/**
 * @brief UpiRestoreData
 *
 *  Restore data from system to IC routine
 *
 * @para  data  address of BackupDataType
 * @return  BACKUP_BOOL_TRUE if success
 */
_backup_bool_ UpiRestoreData(BackupDataType *data)
{
  _backup_bool_ rtn;
  _backup_u32_ driverVer;
  SystemDataType *orgSysData;
  _backup_s32_ tmp32;

  /// [AT-PM] : Create buffer ; 02/21/2013
  #ifndef UG31XX_SHELL_ALGORITHM
    orgSysData = &CheckBackupFile_orgSysData;
  #else   ///< else of UG31XX_SHELL_ALGORITHM
    orgSysData = (SystemDataType *)upi_malloc(sizeof(SystemDataType));
  #endif  ///< end of UG31XX_SHELL_ALGORITHM
  upi_memcpy(orgSysData, ptrSysData, sizeof(SystemDataType));

  /// [AT-PM] : Get data from file ; 02/21/2013
  #if defined (uG31xx_OS_WINDOWS)
  rtn = read_backup_file(data->backupFileName, data->backupBuffer, data->backupBufferSize);
  #else  ///< else of defined (uG31xx_OS_WINDOWS)
  rtn = read_backup_file(ptrBackupFileName, data->backupBuffer, data->backupBufferSize);
  #endif ///< end of defined (uG31xx_OS_WINDOWS)
  if(rtn == _UPI_FALSE_)
  {
    UG31_LOGE("[%s]: Read data from backup file fail.\n", __func__);
    #ifdef  UG31XX_SHELL_ALGORITHM
      upi_free(orgSysData);
    #endif  ///< end of UG31XX_SHELL_ALGORITHM
    return (BACKUP_BOOL_FALSE);
  }
  driverVer = ConvertData(data);
  UG31_LOGI("[%s]: Driver version = %d\n", __func__, (int)driverVer);

  /// [AT-PM] : Keep following information ; 01/22/2014
  ptrSysData->timeTagFromIC = orgSysData->timeTagFromIC;
  ptrSysData->tableUpdateIdxFromIC = orgSysData->tableUpdateIdxFromIC;

  /// [AT-PM] : Check abnormal condition ; 01/22/2014
  if((data->backupVolt1 != 0) && (data->backupVolt2 != 0))
  {
    tmp32 = (_backup_s32_)data->backupVolt1;
    tmp32 = tmp32 - data->backupVolt2;
    if((tmp32 < RESTORE_ABNORMAL_VOLT_RANGE_UPBND) && (tmp32 > RESTORE_ABNORMAL_VOLT_RANGE_LWBND))
    {
      ptrSysData->rmFromIC = orgSysData->rmFromIC;
      ptrSysData->fccFromIC = orgSysData->fccFromIC;
      ptrSysData->rsocFromIC = orgSysData->rsocFromIC;
    }
  }
  #ifdef  UG31XX_SHELL_ALGORITHM
    upi_free(orgSysData);
  #endif  ///< end of UG31XX_SHELL_ALGORITHM
  return (BACKUP_BOOL_TRUE);
}
/**
 * @brief UpiSaveResumeData
 *
 *  Save resume data for backup
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void UpiSaveResumeData(BackupDataType *data)
{
  data->backupSuspendData[data->backupSuspendIdx].afterCapData = *(data->capData);
  data->backupSuspendData[data->backupSuspendIdx].afterMeasData = *(data->measData);
  UG31_LOGN("[%s]: Save resume data to buffer %d\n", __func__, data->backupSuspendIdx);

  data->backupSuspendIdx = data->backupSuspendIdx + 1;
  if(data->backupSuspendIdx >= BACKUP_MAX_LOG_SUSPEND_DATA)
  {
    data->backupSuspendIdx = 0;
    while(data->backupSuspendIdx < (BACKUP_MAX_LOG_SUSPEND_DATA - 1))
    {
      upi_memcpy(&data->backupSuspendData[data->backupSuspendIdx], 
                 &data->backupSuspendData[data->backupSuspendIdx + 1], 
                 sizeof(BackupSuspendDataType));
      data->backupSuspendIdx = data->backupSuspendIdx + 1;
    }

    upi_memset(&data->backupSuspendData[data->backupSuspendIdx], 0, sizeof(BackupSuspendDataType));
    UG31_LOGN("[%s]: Next suspend / resume data buffer is %d\n", __func__, data->backupSuspendIdx);
  }
}
/**
 * @brief PrepareData
 *
 *  Prepare data to be written to file
 *
 * @para  data  address of BackupDataType
 * @return  NULL
 */
void PrepareData(BackupDataType *data)
{
  _backup_u8_ *ptr;
  _backup_u32_ driverVer;
  
  driverVer = (_backup_u32_)UG31XX_DRIVER_VERSION;
  UG31_LOGN("[%s]: Driver version = %d (%d)\n", __func__, (int)driverVer, UG31XX_DRIVER_VERSION);

  upi_memcpy(&data->backupCustomerSelfDef[0], (_backup_u8_ *)&data->sysData->ggbParameter->customerSelfDef, CELL_PARAMETER_STRING_LENGTH);
  UG31_LOGN("[%s]: CustomerSelfDef = %s\n", __func__,
            data->backupCustomerSelfDef);
  upi_memcpy(&data->backupProjectSelfDef[0], (_backup_u8_ *)&data->sysData->ggbParameter->projectSelfDef, CELL_PARAMETER_STRING_LENGTH);
  UG31_LOGN("[%s]: ProjectSelfDef = %s\n", __func__,
            data->backupProjectSelfDef);
  
  ptr = data->backupBuffer;
  upi_memcpy(ptr, (_backup_u8_ *)data->capData->encriptTable, (_upi_u32_)data->capData->tableSize);
  ptr = ptr + data->capData->tableSize;
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->rmFromIC, sizeof(data->sysData->rmFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->rmFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->fccFromIC, sizeof(data->sysData->fccFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->fccFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->timeTagFromIC, sizeof(data->sysData->timeTagFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->timeTagFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->tableUpdateIdxFromIC, sizeof(data->sysData->tableUpdateIdxFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->tableUpdateIdxFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->deltaCapFromIC, sizeof(data->sysData->deltaCapFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->deltaCapFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->adc1ConvTime, sizeof(data->sysData->adc1ConvTime)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->adc1ConvTime)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->rsocFromIC, sizeof(data->sysData->rsocFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->rsocFromIC)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->cycleCount, sizeof(data->sysData->cycleCount)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->cycleCount)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->ccOffset, sizeof(data->sysData->ccOffset)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->ccOffset)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->predictRsoc, sizeof(data->sysData->predictRsoc)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->predictRsoc)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->sysData->standbyDsgRatio, sizeof(data->sysData->standbyDsgRatio)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->standbyDsgRatio)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->backupVolt1, sizeof(data->backupVolt1)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->backupVolt1)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->backupVolt2, sizeof(data->backupVolt2)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->backupVolt2)/sizeof(_backup_u8_);
  upi_memcpy(ptr, (_backup_u8_ *)&data->capData->preDsgCharge, sizeof(data->capData->preDsgCharge)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->capData->preDsgCharge)/sizeof(_backup_u8_);
  upi_memcpy(ptr, &data->backupCustomerSelfDef[0], CELL_PARAMETER_STRING_LENGTH);
  ptr = ptr + CELL_PARAMETER_STRING_LENGTH;
  upi_memcpy(ptr, &data->backupProjectSelfDef[0], CELL_PARAMETER_STRING_LENGTH);
  ptr = ptr + CELL_PARAMETER_STRING_LENGTH;
  upi_memcpy(ptr, (_backup_u8_ *)&driverVer, sizeof(driverVer)/sizeof(_backup_u8_));
}
/**
 * @brief CheckBackupFile
 *
 *  Check backup file is consisted with IC or not
 *
 * @para  data  address of BackupDataType
 * @return  CHECK_BACKUP_FILE_STS
 */
_backup_u8_ CheckBackupFile(BackupDataType *data)
{
  CapacityDataType *orgCapData;
  SystemDataType *orgSysData;
  _upi_bool_ rtn;
  _backup_u32_ driverVer;
  _backup_u8_ rtnU8;
  _backup_u16_ volt1;
  _backup_u16_ volt2;

  /// [AT-PM] : Create buffer ; 02/21/2013
  #ifndef UG31XX_SHELL_ALGORITHM
    orgCapData = &CheckBackupFile_orgCapData;
    orgSysData = &CheckBackupFile_orgSysData;
  #else   ///< else of UG31XX_SHELL_ALGORITHM
    orgCapData = (CapacityDataType *)upi_malloc(sizeof(CapacityDataType));
    orgSysData = (SystemDataType *)upi_malloc(sizeof(SystemDataType));
  #endif  ///< end of UG31XX_SHELL_ALGORITHM
  upi_memcpy(orgCapData, data->capData, sizeof(CapacityDataType));
  upi_memcpy(orgSysData, data->sysData, sizeof(SystemDataType));
  volt1 = data->backupVolt1;
  volt2 = data->backupVolt2;

  /// [AT-PM] : Get data from file ; 02/21/2013
  rtn = read_backup_file(data->backupFileName, data->backupBuffer, data->backupBufferSize);
  if(rtn == _UPI_FALSE_)
  {
    UG31_LOGD("[%s]: Read data from backup file fail.\n", __func__);
    #ifdef  UG31XX_SHELL_ALGORITHM
      upi_free(orgCapData);
      upi_free(orgSysData);
    #endif  ///< end of UG31XX_SHELL_ALGORITHM
    return (CHECK_BACKUP_FILE_STS_READ_FAIL);
  }
  driverVer = ConvertData(data);

  /// [AT-PM] : Following information is not checked ; 02/21/2013
  data->sysData->rmFromIC = orgSysData->rmFromIC;
  data->sysData->timeTagFromIC = orgSysData->timeTagFromIC;
  data->sysData->deltaCapFromIC = orgSysData->deltaCapFromIC;
  data->sysData->adc1ConvTime = orgSysData->adc1ConvTime;
  data->capData->preDsgCharge = orgCapData->preDsgCharge;
  
  /// [AT-PM] : Check data ; 02/21/2013
  if(driverVer != UG31XX_DRIVER_VERSION)
  {
    UG31_LOGN("[%s]: Backup file version mismatched.\n", __func__);
    rtnU8 = CHECK_BACKUP_FILE_STS_VERSION_MISMATCH;
  }
  else if((upi_memcmp(data->backupCustomerSelfDef, data->sysData->ggbParameter->customerSelfDef, CELL_PARAMETER_STRING_LENGTH) != 0) ||
           (upi_memcmp(data->backupProjectSelfDef, data->sysData->ggbParameter->projectSelfDef, CELL_PARAMETER_STRING_LENGTH) != 0))
  {
    UG31_LOGN("[%s]: Backup file cell information mismatched.\n", __func__);
    rtnU8 = CHECK_BACKUP_FILE_STS_VERSION_MISMATCH;
  }
  else if((upi_memcmp(orgCapData, data->capData, sizeof(CapacityDataType)) != 0) ||
          (upi_memcmp(orgSysData, data->sysData, sizeof(SystemDataType)) != 0) ||
          (volt1 != data->backupVolt1) ||
          (volt2 != data->backupVolt2))
  {
    UG31_LOGN("[%s]: Backup file needs to be updated\n", __func__);
    rtnU8 = CHECK_BACKUP_FILE_STS_NEED_UPDATE;
  }
  else
  {
    rtnU8 = CHECK_BACKUP_FILE_STS_PASS;
  }
  #ifdef  UG31XX_SHELL_ALGORITHM
    upi_free(orgCapData);
    upi_free(orgSysData);
  #endif  ///< end of UG31XX_SHELL_ALGORITHM
  return (rtnU8);
}
/**
 * @brief ConvertData
 *
 *  Convert data from buffer
 *
 * @para  data  address of BackupDataType structure
 * @return  driver version
 */
_backup_u32_ ConvertData(BackupDataType *data)
{
  _backup_u8_ *ptr;
  _backup_u32_ driverVer;

  ptr = data->backupBuffer;
  upi_memcpy((_backup_u8_ *)data->capData->encriptTable, ptr, (_upi_u32_)data->capData->tableSize);
  ptr = ptr + data->capData->tableSize;
  upi_memcpy((_backup_u8_ *)&data->sysData->rmFromIC, ptr, sizeof(data->sysData->rmFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->rmFromIC)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->fccFromIC, ptr, sizeof(data->sysData->fccFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->fccFromIC)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->timeTagFromIC, ptr, sizeof(data->sysData->timeTagFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->timeTagFromIC)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->tableUpdateIdxFromIC, ptr, sizeof(data->sysData->tableUpdateIdxFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->tableUpdateIdxFromIC)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->deltaCapFromIC, ptr, sizeof(data->sysData->deltaCapFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->deltaCapFromIC)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->adc1ConvTime, ptr, sizeof(data->sysData->adc1ConvTime)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->adc1ConvTime)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->rsocFromIC, ptr, sizeof(data->sysData->rsocFromIC)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->rsocFromIC)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->cycleCount, ptr, sizeof(data->sysData->cycleCount)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->cycleCount)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->ccOffset, ptr, sizeof(data->sysData->ccOffset)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->ccOffset)/sizeof(_backup_u8_);
  upi_memcpy((_backup_u8_ *)&data->sysData->predictRsoc, ptr, sizeof(data->sysData->predictRsoc)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->predictRsoc)/sizeof(_backup_u8_);  
  upi_memcpy((_backup_u8_ *)&data->sysData->standbyDsgRatio, ptr, sizeof(data->sysData->standbyDsgRatio)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->sysData->standbyDsgRatio)/sizeof(_backup_u8_);  
  upi_memcpy((_backup_u8_ *)&data->backupVolt1, ptr, sizeof(data->backupVolt1)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->backupVolt1)/sizeof(_backup_u8_);  
  upi_memcpy((_backup_u8_ *)&data->backupVolt2, ptr, sizeof(data->backupVolt2)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->backupVolt2)/sizeof(_backup_u8_);  
  upi_memcpy((_backup_u8_ *)&data->capData->preDsgCharge, ptr, sizeof(data->capData->preDsgCharge)/sizeof(_backup_u8_));
  ptr = ptr + sizeof(data->capData->preDsgCharge)/sizeof(_backup_u8_);  
  upi_memcpy(&data->backupCustomerSelfDef[0], ptr, CELL_PARAMETER_STRING_LENGTH);
  ptr = ptr + CELL_PARAMETER_STRING_LENGTH;
  upi_memcpy(&data->backupProjectSelfDef[0], ptr, CELL_PARAMETER_STRING_LENGTH);
  ptr = ptr + CELL_PARAMETER_STRING_LENGTH;
  upi_memcpy((_backup_u8_ *)&driverVer, ptr, sizeof(driverVer)/sizeof(_backup_u8_));
  UG31_LOGI("[%s]: Read driver version = %d (%d)\n", __func__, (int)driverVer, UG31XX_DRIVER_VERSION);
  return (driverVer);
}