/*
 * ****************************************************
 * @file    : flash.c
 * @brief   : Flash Program Body
 * @author  : sohee kim / Something by People
 * @data    : 2023. 04. 27
 * ****************************************************
 */

#include "flash.h"


EEPROM Data_Form Origin_Data={
  {HW_MODEL,HW_VER},              //uint8_t model[2];
  VER_MAJER,
  VER_MINER,

  VER_YEAR,
  VER_MONTH,
  VER_DATE,

  MOTOR_PARA_POLE,                //uint8_t
  VER_SUB,                        //uint8_t   ///somebp 2024.02.07
  MOTOR_ANG_ENCPULSE,             //uint16_t

  MOTOR_PARA_Ld,
  MOTOR_PARA_Lq,
  MOTOR_PARA_Rs,
  MOTOR_PARA_PhaiF,

  MOTOR_GAINCURD_Kp,
  MOTOR_GAINCURD_Ki,
  MOTOR_GAINCURD_Kaw,
  MOTOR_GAINCURQ_Kp,
  MOTOR_GAINCURQ_Ki,
  MOTOR_GAINCURQ_Kaw,

  MOTOR_GAINSPD_Kp,
  MOTOR_GAINSPD_Ki,
  MOTOR_GAINSPD_Kaw,

  MOTOR_GAINFWEAK_Kp,
  MOTOR_GAINFWEAK_Ki,

  MOTOR_ANG_ANGLESCALE,
  MOTOR_ANG_SPEEDSCALE,
  MOTOR1_ANG_ANGLEELCOFFSET,
  MOTOR2_ANG_ANGLEELCOFFSET,

  MOTOR_ANG_MR_MAX_SIN,           //uint16_t
  MOTOR_ANG_MR_MAX_COS,           //uint16_t
  MOTOR_ANG_MR_MIN_SIN,           //uint16_t
  MOTOR_ANG_MR_MIN_COS,           //uint16_t
  MOTOR_ANG_MR_MID_SIN,           //uint16_t
  MOTOR_ANG_MR_MID_COS,           //uint16_t
  MOTOR_ANG_MR_GAIN_SIN,
  MOTOR_ANG_MR_GAIN_COS,

  INV_PARA_HWADCSCALE,
  INV_PARA_HWVDCSCALE,
  INV_PARA_HWISCALE,

  INV_PARA_TSAMP,

  INV_PARA_PWM_MAX,
  INV_PARA_PWM_MID,
  INV_PARA_VDCMARGIN,

  LPFVDC_FC,
  LPFVDC_FS,

  LPFCUR_FC,
  LPFCUR_FS,

  LPFSPD_FC,
  LPFSPD_FS,

  ERRREF_ISENSOROPEN,
  ERRREF_ISENSORSHORT,
  ERRREF_OVERCURRENT,
  ERRREF_OVERSPEED,
  ERRREF_OVERVOLTAGE,
  ERRREF_UNDERVOLTAGE,
  ERRREF_ISENSOROFFSETMAX,
  ERRREF_ISENSOROFFSETMIN,

  INV_CTRL_VDCLIMFWEAK,
  INV_CTRL_ILIMFWEAK,

  MOTOR_ANG_RPMLIM,
  MOTOR_ANG_SPDCTRLOUTLIM,

  MACHINE_SENSOR_GEAR_RATIO,
  MACHINE_SPOOL_DIAMETER,
  MACHINE_MAX_WEIGHT,
  MACHINE_CABLE_MAX_LENGTH,
  MACHINE_SCALE_WEIGHT2CURRENT,
  MACHINE_SOFT_WINDING_HEIGHT,

  MACHINE_DEFAULT_WEIGHT,
  MACHINE_FRICTION_WEIGHT,
  MACHINE_FRICTION_SPEED_PLUS,
  MACHINE_FRICTION_SPEED_MINUS,

  FLASH_VALID_CODE,//uint32_t check
};

BACKUP Data_Form Backup_Data={
  {HW_MODEL,HW_VER},              //uint8_t model[2];
  VER_MAJER,
  VER_MINER,

  VER_YEAR,
  VER_MONTH,
  VER_DATE,

  MOTOR_PARA_POLE,                //uint8_t
  VER_SUB,                        //uint8_t   ///somebp 2024.02.07
  MOTOR_ANG_ENCPULSE,             //uint16_t

  MOTOR_PARA_Ld,
  MOTOR_PARA_Lq,
  MOTOR_PARA_Rs,
  MOTOR_PARA_PhaiF,

  MOTOR_GAINCURD_Kp,
  MOTOR_GAINCURD_Ki,
  MOTOR_GAINCURD_Kaw,
  MOTOR_GAINCURQ_Kp,
  MOTOR_GAINCURQ_Ki,
  MOTOR_GAINCURQ_Kaw,

  MOTOR_GAINSPD_Kp,
  MOTOR_GAINSPD_Ki,
  MOTOR_GAINSPD_Kaw,

  MOTOR_GAINFWEAK_Kp,
  MOTOR_GAINFWEAK_Ki,

  MOTOR_ANG_ANGLESCALE,
  MOTOR_ANG_SPEEDSCALE,
  MOTOR1_ANG_ANGLEELCOFFSET,
  MOTOR2_ANG_ANGLEELCOFFSET,

  MOTOR_ANG_MR_MAX_SIN,           //uint16_t
  MOTOR_ANG_MR_MAX_COS,           //uint16_t
  MOTOR_ANG_MR_MIN_SIN,           //uint16_t
  MOTOR_ANG_MR_MIN_COS,           //uint16_t
  MOTOR_ANG_MR_MID_SIN,           //uint16_t
  MOTOR_ANG_MR_MID_COS,           //uint16_t
  MOTOR_ANG_MR_GAIN_SIN,
  MOTOR_ANG_MR_GAIN_COS,

  INV_PARA_HWADCSCALE,
  INV_PARA_HWVDCSCALE,
  INV_PARA_HWISCALE,

  INV_PARA_TSAMP,

  INV_PARA_PWM_MAX,
  INV_PARA_PWM_MID,
  INV_PARA_VDCMARGIN,

  LPFVDC_FC,
  LPFVDC_FS,

  LPFCUR_FC,
  LPFCUR_FS,

  LPFSPD_FC,
  LPFSPD_FS,

  ERRREF_ISENSOROPEN,
  ERRREF_ISENSORSHORT,
  ERRREF_OVERCURRENT,
  ERRREF_OVERSPEED,
  ERRREF_OVERVOLTAGE,
  ERRREF_UNDERVOLTAGE,
  ERRREF_ISENSOROFFSETMAX,
  ERRREF_ISENSOROFFSETMIN,

  INV_CTRL_VDCLIMFWEAK,
  INV_CTRL_ILIMFWEAK,

  MOTOR_ANG_RPMLIM,
  MOTOR_ANG_SPDCTRLOUTLIM,

  MACHINE_SENSOR_GEAR_RATIO,
  MACHINE_SPOOL_DIAMETER,
  MACHINE_MAX_WEIGHT,
  MACHINE_CABLE_MAX_LENGTH,
  MACHINE_SCALE_WEIGHT2CURRENT,
  MACHINE_SOFT_WINDING_HEIGHT,

  MACHINE_DEFAULT_WEIGHT,
  MACHINE_FRICTION_WEIGHT,
  MACHINE_FRICTION_SPEED_PLUS,
  MACHINE_FRICTION_SPEED_MINUS,

  FLASH_VALID_CODE,//uint32_t check;
};

const Data_Form_RAM Defualt_RAM_Data={
  {HW_MODEL,HW_VER},              //uint8_t model[2];
  VER_MAJER,
  VER_MINER,

  VER_YEAR,
  VER_MONTH,
  VER_DATE,

  MOTOR_PARA_POLE,                //uint8_t
  VER_SUB,                        //uint8_t   ///somebp 2024.02.07
  MOTOR_ANG_ENCPULSE,             //uint16_t

  MOTOR_PARA_Ld,
  MOTOR_PARA_Lq,
  MOTOR_PARA_Rs,
  MOTOR_PARA_PhaiF,

  MOTOR_GAINCURD_Kp,
  MOTOR_GAINCURD_Ki,
  MOTOR_GAINCURD_Kaw,
  MOTOR_GAINCURQ_Kp,
  MOTOR_GAINCURQ_Ki,
  MOTOR_GAINCURQ_Kaw,

  MOTOR_GAINSPD_Kp,
  MOTOR_GAINSPD_Ki,
  MOTOR_GAINSPD_Kaw,

  MOTOR_GAINFWEAK_Kp,
  MOTOR_GAINFWEAK_Ki,

  MOTOR_ANG_ANGLESCALE,
  MOTOR_ANG_SPEEDSCALE,
  MOTOR1_ANG_ANGLEELCOFFSET,
  MOTOR2_ANG_ANGLEELCOFFSET,

  MOTOR_ANG_MR_MAX_SIN,           //uint16_t
  MOTOR_ANG_MR_MAX_COS,           //uint16_t
  MOTOR_ANG_MR_MIN_SIN,           //uint16_t
  MOTOR_ANG_MR_MIN_COS,           //uint16_t
  MOTOR_ANG_MR_MID_SIN,           //uint16_t
  MOTOR_ANG_MR_MID_COS,           //uint16_t
  MOTOR_ANG_MR_GAIN_SIN,
  MOTOR_ANG_MR_GAIN_COS,

  INV_PARA_HWADCSCALE,
  INV_PARA_HWVDCSCALE,
  INV_PARA_HWISCALE,

  INV_PARA_TSAMP,

  INV_PARA_PWM_MAX,
  INV_PARA_PWM_MID,
  INV_PARA_VDCMARGIN,

  LPFVDC_FC,
  LPFVDC_FS,

  LPFCUR_FC,
  LPFCUR_FS,

  LPFSPD_FC,
  LPFSPD_FS,

  ERRREF_ISENSOROPEN,
  ERRREF_ISENSORSHORT,
  ERRREF_OVERCURRENT,
  ERRREF_OVERSPEED,
  ERRREF_OVERVOLTAGE,
  ERRREF_UNDERVOLTAGE,
  ERRREF_ISENSOROFFSETMAX,
  ERRREF_ISENSOROFFSETMIN,

  INV_CTRL_VDCLIMFWEAK,
  INV_CTRL_ILIMFWEAK,

  MOTOR_ANG_RPMLIM,
  MOTOR_ANG_SPDCTRLOUTLIM,

  MACHINE_SENSOR_GEAR_RATIO,
  MACHINE_SPOOL_DIAMETER,
  MACHINE_MAX_WEIGHT,
  MACHINE_CABLE_MAX_LENGTH,
  MACHINE_SCALE_WEIGHT2CURRENT,
  MACHINE_SOFT_WINDING_HEIGHT,

  MACHINE_DEFAULT_WEIGHT,
  MACHINE_FRICTION_WEIGHT,
  MACHINE_FRICTION_SPEED_PLUS,
  MACHINE_FRICTION_SPEED_MINUS,

  FLASH_VALID_CODE,//uint32_t check;
};

Data_Form_RAM RAM_Data;


void Flash_Init(void)
{
  uint8_t i;
  uint32_t *ram_data,*source_data;

  ram_data=(uint32_t*)&RAM_Data;

  if(Origin_Data.check==FLASH_VALID_CODE) {
    source_data=(uint32_t*)&Origin_Data;
    for(i=0; i<sizeof(RAM_Data)/4;i++ ) {
      *ram_data++=*source_data++;
    }
    //write backup
    Flash_Write(FLASH_BACKUP_SECTOR);
    Flash_Write(FLASH_BACKUP_SECTOR);
  }
  else if(Backup_Data.check==FLASH_VALID_CODE) {
    source_data=(uint32_t*)&Backup_Data;
    for(i=0; i<sizeof(RAM_Data)/4;i++) {
      *ram_data++=*source_data++;
    }
    //write origin
    Flash_Write(FLASH_ORIGIN_SECTOR);
    Flash_Write(FLASH_ORIGIN_SECTOR);
  }
  else {                       //Factory Reset
    source_data=(uint32_t*)&Defualt_RAM_Data;
    for(i=0; i<sizeof(RAM_Data)/4;i++) {
      *ram_data++=*source_data++;
    }
    //write origin
    Flash_Write(FLASH_ORIGIN_SECTOR);
    Flash_Write(FLASH_ORIGIN_SECTOR);
  }
}

HAL_StatusTypeDef Flash_Erase(uint32_t sector)
{
  uint32_t SectorError=0;

  HAL_FLASH_Unlock();

  FLASH_EraseInitTypeDef  EraseInitStruct;

  EraseInitStruct.TypeErase=FLASH_TYPEERASE_SECTORS;
  EraseInitStruct.Sector=sector;
  EraseInitStruct.NbSectors=1;
  EraseInitStruct.VoltageRange=FLASH_VOLTAGE_RANGE_3;

  if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError)!=HAL_OK){
    return HAL_ERROR;
  }
  HAL_FLASH_Lock();
  Delay_msec(10);
  return HAL_OK;

}

/**
  * @brief  Set the specified data holding register value for DAC channel.
  * @param  Sector  Target Sector Number
  *          This parameter can be one of the following values:
  *            @arg FLASH_ORIGIN_SECTOR
  *            @arg FLASH_BACKUP_SECTOR
  * @retval HAL status
  */
HAL_StatusTypeDef Flash_Write(uint8_t sector)
{
  uint8_t i;
  const uint32_t t=sizeof(Data_Form_RAM)/4;
  uint32_t *ram_data,*flash_data;

  ram_data=(uint32_t*)&RAM_Data;
  if(sector==FLASH_ORIGIN_SECTOR){//origin
    flash_data=(uint32_t*)&Origin_Data;

    for(i=0; i<t; i++) {
      if(*ram_data++!=*flash_data++)    break;
    }
    if(i==t)                            return HAL_OK;

    ram_data=(uint32_t*)&RAM_Data;
    flash_data=(uint32_t*)&Origin_Data;   //target

    //Erase
    HAL_FLASH_Unlock();
    Flash_Erase(FLASH_ORIGIN_SECTOR);
    HAL_FLASH_Lock();
    Delay_msec(10);

    //Write
    HAL_FLASH_Unlock();
    for(i=0; i<t; i++) {
      if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)flash_data++, *ram_data++)!=HAL_OK) {
        return HAL_ERROR;
      }
    }
    Delay_msec(10);
    HAL_FLASH_Lock();
  }
  if(sector==FLASH_BACKUP_SECTOR){//backup
    flash_data=(uint32_t*)&Backup_Data;

    for(i=0; i<t; i++) {
      if(*ram_data++!=*flash_data++)    break;
    }
    if(i==t)                            return HAL_OK;

    ram_data=(uint32_t*)&RAM_Data;
    flash_data=(uint32_t*)&Backup_Data;   //target

    //Erase
    HAL_FLASH_Unlock();
    Flash_Erase(FLASH_BACKUP_SECTOR);
    HAL_FLASH_Lock();
    Delay_msec(10);

    //Write
    HAL_FLASH_Unlock();
    for(i=0; i<t; i++) {
      if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)flash_data++, *ram_data++)!=HAL_OK) {
        return HAL_ERROR;
      }
    }
    Delay_msec(10);
    HAL_FLASH_Lock();
  }
  return HAL_OK;
}

