//https://controllerstech.com/eeprom-and-stm32/

#include "eeprom.h"
#include "stdio.h"
#include "math.h"

#define CONCAT(a, b) CONCAT_INNER(a, b)											// These three macros
#define CONCAT_INNER(a, b) a ## b												// generate unique variables
#define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)								// according to template "baseX", like "base1", "base2" and etc

// Define the I2C
extern I2C_HandleTypeDef hi2c3;
#define EEPROM_I2C &hi2c3

// EEPROM ADDRESS (8bits)
#define EEPROM_ADDR 0xA0

// Define the Page Size and number of pages
#define PAGE_SIZE 64     // in Bytes
#define PAGE_NUM  4096    // number of pages

/********************************************************/

// Eeprom state related defines

/*****************EEPROM_EMULATOR************************/

typedef struct
{
  // Schnittstellenparameter
  uint32_t	  baudrate;
  uint16_t	  parityMode;
  uint16_t	  stopBits;
  uint16_t	  slave_adress;
  uint16_t	  ibn_day;
  uint16_t	  ibn_month;
  uint16_t	  ibn_year;
  uint16_t	  user_id;

  // Offset und Gain
  int16_t	  batteryCurrentOffsetRefTemperatureShunt;
  int16_t	  batteryCurrentOffsetRefTemperatureChip;
  int16_t	  batteryCurrentGainRefTempShunt;
  int16_t	  batteryCurrentGainRefTempChip;
  int16_t	  batteryCurrentOffsetTemperatureCalibrationTemperature;
  int16_t	  batteryCurrentGainTemperatureCalibrationShuntTemperature;
  int16_t	  batteryCurrentGainTemperatureCalibrationChipTemperature;
  int32_t	  batteryCurrentOffsetRefshuntVoltage;
  int32_t	  batteryCurrentOffsetCommonModeCalibrationVoltage;
  int32_t	  batteryCurrentOffsetCommonModeCompensationFactor;
  int32_t	  batteryCurrentOffsetTemperatureCompensationFactor;
  int32_t	  batteryCurrentGainRefCurrent;
  int32_t	  batteryCurrentGainTemperatureCompensationShuntFactor;
  int32_t	  batteryCurrentGainTemperatureCompensationChipFactor;

  int32_t	  currentOffset;
  uint32_t	  currentGain;

  int64_t	  mAsCounter;
  int32_t	  detectedCapacity;
  int32_t	  detectedEnergy;
  int64_t	  mAs_AutoMode;								// 160-163	Helps to restore current SoC after Reset or Shutdown
  int64_t	  mWs_AutoMode;								// 164-167	Helps to restore current SoC after Reset or Shutdown

  // battery parameter
  uint16_t	  cef;
  uint16_t	  peukert;
  uint32_t	  cellCapacity;
  uint32_t	  cellEnergy;
  uint16_t	  iBatFull;
  uint16_t	  tBatFull;
  uint16_t	  uBatFull;
  uint16_t	  uBatEmpty;
  uint8_t	  socCalcMode;
  uint16_t	  cellRatedDischargeTime;

  // Schaltausgänge
  uint16_t	  lvpStart;									// Spannung ab der die LOW Voltage Protection aktiv wird in mV
  uint16_t	  lvpStop;									// Spannung ab der die LOW Voltage Protection wieder inaktiv wird
  uint16_t	  ovpStart;									// Spannung ab der die OVER Voltage Protection aktiv wird in mV
  uint16_t	  ovpStop;									// Spannung ab der die OVER Voltage Protection wieder inaktiv wird
  int16_t	  loadCurrentLimit;							// maximaler Laststrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Laststrom Protection aktiv
  int16_t	  chargeCurrentLimit;						// maximaler Ladestrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Ladestrom Protection aktiv
  int16_t	  chargeStopHighTemperatureStart;			// Abschalttemperatur Ladung wegen zu hoher Temperatur
  int16_t	  chargeStopHighTemperatureStop;			// Wiedereinschalttemperatur
  int16_t	  chargeStopLowTemperatureStart;			// Abschalttemperatur Ladung wegen zu niedriger Temperatur
  int16_t	  chargeStopLowTemperatureStop;				// Wiedereinschalttemperatur
  int16_t	  dischargeStopHighTemperatureStart;		// Abschalttemperatur Entladung wegen zu hoher Temperatur
  int16_t	  dischargeStopHighTemperatureStop;			// Wiedereinschalttemperatur
  int16_t	  dischargeStopLowTemperatureStart;			// Abschalttemperatur EntLadung wegen zu niedriger Temperatur
  int16_t	  dischargeStopLowTemperatureStop;			// Wiedereinschalttemperatur

  int16_t	  uBatEmptyCompStartTemp;					// We start calculating uBatEmpty compensations only when cell temperature is lower than this value
  int16_t	  uBatEmptyCompStopTemp;					// We stop calculating uBatEmpty compensations when cell temperature is lower than this value
  uint16_t	  uBatEmptyCompStopVolt;					// uBatEmpty Voltage at temperatures lower than lvpCompStopTemp

  int16_t	  extraDischargeStrom_mA;					// For example, current that consumes LiPro itself
  uint32_t	  dischargeTotalAh;
  uint32_t	  chargeTotalAh;
  uint32_t	  dischargeTotalWh;							// 154-155	[mAs]
  uint32_t	  chargeTotalWh;							// 156-157	[mAs]

  uint16_t	  cefW;
  uint32_t	  onTime;

} eeprom_data_t;

typedef struct
{
  // Schnittstellenparameter
  uint32_t	  baudrate;
  uint16_t	  parityMode;
  uint16_t	  stopBits;
  uint16_t	  slave_adress;
  uint16_t	  ibn_day;
  uint16_t	  ibn_month;
  uint16_t	  ibn_year;
  uint16_t	  user_id;

  // Offset und Gain
  int16_t	  batteryCurrentOffsetRefTemperatureShunt;
  int16_t	  batteryCurrentOffsetRefTemperatureChip;
  int16_t	  batteryCurrentGainRefTempShunt;
  int16_t	  batteryCurrentGainRefTempChip;
  int16_t	  batteryCurrentOffsetTemperatureCalibrationTemperature;
  int16_t	  batteryCurrentGainTemperatureCalibrationShuntTemperature;
  int16_t	  batteryCurrentGainTemperatureCalibrationChipTemperature;
  int32_t	  batteryCurrentOffsetRefshuntVoltage;
  int32_t	  batteryCurrentOffsetCommonModeCalibrationVoltage;
  int32_t	  batteryCurrentOffsetCommonModeCompensationFactor;
  int32_t	  batteryCurrentOffsetTemperatureCompensationFactor;
  int32_t	  batteryCurrentGainRefCurrent;
  int32_t	  batteryCurrentGainTemperatureCompensationShuntFactor;
  int32_t	  batteryCurrentGainTemperatureCompensationChipFactor;

  int32_t	  currentOffset;
  uint32_t	  currentGain;

  int64_t	  mAsCounter;
  int32_t	  detectedCapacity;
  int32_t	  detectedEnergy;
  int32_t	  mAh_AutoMode;
  int32_t	  mWh_AutoMode;

  // battery parameter
  uint16_t	  cef;
  uint16_t	  peukert;
  uint32_t	  cellCapacity;
  uint32_t	  cellEnergy;
  uint16_t	  iBatFull;
  uint16_t	  tBatFull;
  uint16_t	  uBatFull;
  uint16_t	  uBatEmpty;
  uint8_t	  socCalcMode;
  uint16_t	  cellRatedDischargeTime;

  // Schaltausgänge
  uint16_t	  lvpStart;									// Spannung ab der die LOW Voltage Protection aktiv wird in mV
  uint16_t	  lvpStop;									// Spannung ab der die LOW Voltage Protection wieder inaktiv wird
  uint16_t	  ovpStart;									// Spannung ab der die OVER Voltage Protection aktiv wird in mV
  uint16_t	  ovpStop;									// Spannung ab der die OVER Voltage Protection wieder inaktiv wird
  int16_t	  loadCurrentLimit;							// maximaler Laststrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Laststrom Protection aktiv
  int16_t	  chargeCurrentLimit;						// maximaler Ladestrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Ladestrom Protection aktiv
  int16_t	  chargeStopHighTemperatureStart;			// Abschalttemperatur Ladung wegen zu hoher Temperatur
  int16_t	  chargeStopHighTemperatureStop;			// Wiedereinschalttemperatur
  int16_t	  chargeStopLowTemperatureStart;			// Abschalttemperatur Ladung wegen zu niedriger Temperatur
  int16_t	  chargeStopLowTemperatureStop;				// Wiedereinschalttemperatur
  int16_t	  dischargeStopHighTemperatureStart;		// Abschalttemperatur Entladung wegen zu hoher Temperatur
  int16_t	  dischargeStopHighTemperatureStop;			// Wiedereinschalttemperatur
  int16_t	  dischargeStopLowTemperatureStart;			// Abschalttemperatur EntLadung wegen zu niedriger Temperatur
  int16_t	  dischargeStopLowTemperatureStop;			// Wiedereinschalttemperatur

  int16_t	  uBatEmptyCompStartTemp;					// We start calculating uBatEmpty compensations only when cell temperature is lower than this value
  int16_t	  uBatEmptyCompStopTemp;					// We stop calculating uBatEmpty compensations when cell temperature is lower than this value
  uint16_t	  uBatEmptyCompStopVolt;					// uBatEmpty Voltage at temperatures lower than lvpCompStopTemp

  int16_t	  extraDischargeStrom_mA;					// For example, current that consumes LiPro itself
  uint32_t	  dischargeTotalAh;
  uint32_t	  chargeTotalAh;
  uint32_t	  dischargeTotalWh;							// 154-155	[mAs]
  uint32_t	  chargeTotalWh;							// 156-157	[mAs]

  uint16_t	  cefW;
  uint32_t	  onTime;

}eeprom_old_data_t;

// Substitute for #if sizeof(some_type) == sizeof(another_type) functionality
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

typedef struct
{
  // Geräteinformation
  uint32_t    SN;
  uint8_t     deviceInfoWritten;
  uint8_t     UNIQUE_NAME(reserved)[3];
}device_info_t;

typedef struct
{
  // Eeprom Status Infos
   uint8_t     firstStartId;
   uint8_t     UNIQUE_NAME(reserved)[3];
  uint16_t     structureSize;
  uint16_t     revisionInfo;
  uint32_t     writeCounter;
}eeprom_state_t;

// fasse zu einer Struktur zusammen um nachher einfach darauf zugreifen zu können
typedef struct
{
  eeprom_state_t eepromState;
  device_info_t  deviceInfo;
  eeprom_data_t  changedData;
}eeprom_stored_data_t;





// Data to store reated defines
//#define SIZEOF_DEFAULT_EEPROM_DATA                (sizeof(eeprom_new_data_t))
#define SIZEOF_CHANGED_EEPROM_DATA                (sizeof(eeprom_data_t))
#define SIZEOF_DEVICE_INFO                        (sizeof(device_info_t))
#define SIZEOF_EEPROM_STATE                       (sizeof(eeprom_state_t))

#define SIZE_OF_DATA_TO_STORE                     (SIZEOF_CHANGED_EEPROM_DATA + SIZEOF_DEVICE_INFO + SIZEOF_EEPROM_STATE)


// Adress related defines
#define EEPROM_ADRESS_FIRST_START_ID              (0)
#define FIRST_START_ID                            (0xFF)
#define CONFIG_ID								  (01)	  // Increment by 1 to make compartible update, more than 1 - incompartible
#if CONFIG_ID == FIRST_START_ID
#error "CONFIG_ID must not be equal to FIRST_START_ID!!! Calibration data will be erased!!!"
#endif



static uint32_t GetPage(uint32_t Address);
static HAL_StatusTypeDef getEEPROMData(uint32_t address, uint8_t * data, uint32_t len);

void EEPROM_Read (uint16_t page, uint16_t offset, uint8_t *data, uint16_t size);
void EEPROM_Write (uint16_t page, uint16_t offset, uint8_t *data, uint16_t size);




// muss modulo 8 noch hinzufügen wg 8 byte alignement
static uint64_t eepromData[(SIZE_OF_DATA_TO_STORE / 8) + 1];


static FLASH_EraseInitTypeDef EraseInitStruct = {0};

static const eeprom_data_t defaultEepromData =
{
	// Schnittstellenparameter

	/* baudrate		*/														19200,			// uint32_t   baudrate;
	/* parityMode	*/														0,				// uint16_t   parityMode;
	/* stopBits		*/														1,				// uint16_t   stopBits;
	/* slave_adress	*/														1,				// uint16_t   slave_adress;
	/* ibn_day		*/														0,				// ibm_day
	/* ibn_month	*/														0,				// ibm_month
	/* ibn_year		*/														0,				// ibm_year
	/* user_id		*/														0,				// user id

	// Offset und Gain

	/* batteryCurrentOffsetRefTemperatureShunt					*/			0,				// int16_t   batteryCurrentOffsetRefTemperatureShunt;
	/* batteryCurrentOffsetRefTemperatureChip					*/			0,				// int16_t   batteryCurrentOffsetRefTemperatureChip
	/* batteryCurrentGainRefTempShunt							*/			0,				// int16_t   batteryCurrentGainRefTempShunt;
	/* batteryCurrentGainRefTempChip							*/			0,				// int16_t   batteryCurrentGainRefTempShip
	/* batteryCurrentOffsetTemperatureCalibrationTemperature	*/			0,				// int16_t   batteryCurrentOffsetTemperatureCalibrationTemperature;
	/* batteryCurrentGainTemperatureCalibrationShuntTemperature	*/			0,				// int16_t   batteryCurrentGainTemperatureCalibrationShuntTemperature;
	/* batteryCurrentGainTemperatureCalibrationChipTemperature	*/			0,				// int16_t   batteryCurrentGainTemperatureCalibrationChipTemperature;
	/* batteryCurrentOffsetRefshuntVoltage						*/			0,				// int32_t   batteryCurrentOffsetRefshuntVoltage;
	/* batteryCurrentOffsetCommonModeCalibrationVoltage			*/			0,				// int32_t   batteryCurrentOffsetCommonModeCalibrationVoltage;
	/* batteryCurrentOffsetTemperatureCompensationFactor		*/			0,				// int32_t   batteryCurrentOffsetTemperatureCompensationFactor;
	/* batteryCurrentOffsetCommonModeCompensationFactor			*/			0,				// int32_t   batteryCurrentOffsetCommonModeCompensationFactor;
	/* batteryCurrentGainRefCurrent								*/			250000,			// int32_t   batteryCurrentGainRefCurrent;
	/* batteryCurrentGainTemperatureCompensationShuntFactor		*/			0,				// int32_t   batteryCurrentGainTemperatureCompensationShuntFactor;
	/* batteryCurrentGainTemperatureCompensationChipFactor		*/			0,				// int32_t   batteryCurrentGainTemperatureCompensationChipFactor;

	/* currentOffset  */													0,				//int32_t   currentOffset;
	/* currentGain	  */													1000000,		//uint32_t  currentGain;

	/* mAsCounter		*/													0,				// mAsCounter
	/* detectedCapacity	*/													-1,				// detectedCapacity
	/* detectedEnergy	*/													-1,				// detectedEnergy
	/* mAs_AutoMode		*/													(-100000LL*3600LL),	// mAs_AutoMode = cellCapacity*3600,
	/* mWs_AutoMode		*/													(-2640000LL*3600LL),// mWs_AutoMode = cellEnergy*3600,

	// battery parameter

	/* cef						*/											99,				// cef
	/* peukert					*/											105,			// peukert
	/* cellCapacity				*/											100000,			// cell Capacity in mAh
	/* cellEnergy				*/											2640000,		// cell energy in mWh
	/* iBatFull					*/											10,				// I-batt full 4% 4A bei 100Ah akku
	/* tBatFull					*/											2,				// t-batt full 2 Sekunden
	/* uBatFull					*/											14000,			// 14Volt Ubatt full
	/* uBatEmpty				*/											12500,			// 11,312V Ubatt Empty
	/* socCalcMode				*/											1,				// SoC calculation mode: 0(default)
	/* cellRatedDischargeTime	*/											2,				// cell rated current discharge time [C/x]. For example, if 40Ah cell is rated as 0.5c, then rated discharge time is 2

	/* lvpStart	*/															12000,			// uint16_t lvpStart; Spannung ab der die LOW Voltage Protection aktiv wird in mV
	/* lvpStop	*/															12500,			// uint16_t lvpStop; Spannung ab der die LOW Voltage Protection wieder inaktiv wird
	/* ovpStart	*/															15000,			// uint16_t  ovpStart; Spannung ab der die OVER Voltage Protection aktiv wird in mV
	/* ovpStop	*/															14000,			// uint16_t  ovpStop; Spannung ab der die OVER Voltage Protection wieder inaktiv wird

#if (DEVICETYPE == 500)
	/* loadCurrentLimit	  */												-500,			// uint16_t loadCurrentLimit; maximaler Laststrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Laststrom Protection aktiv
	/* chargeCurrentLimit */												500,			// uint16_t chargeCurrentLimit;	maximaler Ladestrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Ladestrom Protection aktiv
#elif (DEVICETYPE == 250)
	/* loadCurrentLimit	  */												-250,			// uint16_t loadCurrentLimit; maximaler Laststrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Laststrom Protection aktiv
	/* chargeCurrentLimit */												250,			// uint16_t chargeCurrentLimit maximaler Ladestrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Ladestrom Protection aktiv
#elif (DEVICETYPE == 125)
	/* loadCurrentLimit	  */												-125,			// uint16_t loadCurrentLimit; maximaler Laststrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Laststrom Protection aktiv
	/* chargeCurrentLimit */												125,			// uint16_t chargeCurrentLimit; maximaler Ladestrom in A wenn der Strom größer ist als der eingestelle Wert dann wird die Ladestrom Protection aktiv
#else
#error No valid device type
#endif
	/* chargeStopHighTemperatureStart	*/									7500,			// 80°C int16_t chargeStopHighTemperatureStart;	Abschalttemperatur Ladung wegen zu hoher Temperatur
	/* chargeStopHighTemperatureStop	*/									7000,			// 75°C int16_t chargeStopHighTemperatureStop;	Wiedereinschalttemperatur
	/* chargeStopLowTemperatureStart	*/									-3500,			// -35°C int16_t chargeStopLowTemperatureStart;	Abschalttemperatur Ladung wegen zu niedriger Temperatur
	/* chargeStopLowTemperatureStop		*/									-3000,			// -30°C int16_t chargeStopLowTemperatureStop; Wiedereinschalttemperatur
	/* dischargeStopHighTemperatureStart*/									7500,			// 80°C int16_t dischargeStopHighTemperatureStart; Abschalttemperatur Entladung wegen zu hoher Temperatur
	/* dischargeStopHighTemperatureStop	*/									7000,			// 75°C int16_t dischargeStopHighTemperatureStop; Wiedereinschalttemperatur
	/* dischargeStopLowTemperatureStart	*/									-3500,			// -35°C int16_t dischargeStopLowTemperatureStart; Abschalttemperatur EntLadung wegen zu niedriger Temperatur
	/* dischargeStopLowTemperatureStop	*/									-3000,			// -30°C int16_t dischargeStopLowTemperatureStop; Wiedereinschalttemperatur

	/* uBatEmptyCompStartTemp	*/											50,				// 5°C We start calculating uBatEmpty compensations only when cell temperature is lower than this value
	/* uBatEmptyCompStopTemp	*/											-200,			// -20°C We stop calculating uBatEmpty compensations when cell temperature is lower than this value
	/* uBatEmptyCompStopVolt	*/											10000,			// 10V uBatEmpty voltage at temperatures lower than -20°C

	/* extraDischargeStrom_mA	*/											7,				// mA, current that LiPro consumes itself
	/* dischargeTotalAh			*/											0,				// Ah for negative current counter
	/* chargeTotalAh			*/											0,				// Ah for total charge counter
	/* dischargeTotalWh			*/											0,
	/* chargeTotalWh			*/											0,

	/* cefW		*/															90,				// 90% cef for Wh calculations
	/* onTime	*/															0

};

/**
  * @brief  Gets the page of a given address
  * @param  Addr: Address of the FLASH Memory
  * @retval The page of a given address
  */
static uint32_t GetPage(uint32_t Addr)
{
  return (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
}


startType_t EEPROM_isFirstStart(void)
{
  // sizeof eeprom_new_data_t must not be equal to size of eeprom_old_data_t
  BUILD_BUG_ON(sizeof(eeprom_data_t) == sizeof(eeprom_old_data_t));

  uint8_t firstStartCatcher;

  EEPROM_Read(0,EEPROM_ADRESS_FIRST_START_ID, &firstStartCatcher, 1);


  if (firstStartCatcher == FIRST_START_ID)
  {
	  printf ("First start detected!\n");
	  return FIRST_START_AFTER_ERASE;
  }
  else if (firstStartCatcher == CONFIG_ID)
  {
	  printf ("Normal start without EEPROM changes detected\n");
	  return FIRST_START_AFTER_COMPARTIBLE_UPDATE;
  }
  else if (firstStartCatcher == CONFIG_ID - 1)
  {
	  printf ("EEPROM was changed! We need to preserve calibration and settings data!\n");
	  return FIRST_START_AFTER_INCOMPARTIBLE_UPDATE;
  }
  else return FIRST_START_ERROR;
}

//------------------------------------------------------------------------------

HAL_StatusTypeDef EEPROM_fullRestore(sys_data_t* data)
{
  eeprom_stored_data_t* dataToStore;
  uint32_t PageError;
  uint32_t Address;
  uint32_t x;

  printf("EEPROM FULL RESTORE!\n");

  /**************** LESE_DEFAULT_WERTE ************************/

  dataToStore = (eeprom_stored_data_t*) eepromData;

  // Schnittstellenparameter
  dataToStore->changedData.baudrate													= defaultEepromData.baudrate;
  dataToStore->changedData.parityMode												= defaultEepromData.parityMode;
  dataToStore->changedData.stopBits													= defaultEepromData.stopBits;
  dataToStore->changedData.slave_adress												= defaultEepromData.slave_adress;

  // Offset und Gain
  dataToStore->changedData.batteryCurrentOffsetRefTemperatureShunt					= defaultEepromData.batteryCurrentOffsetRefTemperatureShunt;
  dataToStore->changedData.batteryCurrentOffsetRefTemperatureChip					= defaultEepromData.batteryCurrentOffsetRefTemperatureChip;
  dataToStore->changedData.batteryCurrentGainRefTempShunt							= defaultEepromData.batteryCurrentGainRefTempShunt;
  dataToStore->changedData.batteryCurrentGainRefTempChip							= defaultEepromData.batteryCurrentGainRefTempChip;
  dataToStore->changedData.batteryCurrentOffsetTemperatureCalibrationTemperature	= defaultEepromData.batteryCurrentOffsetTemperatureCalibrationTemperature;
  dataToStore->changedData.batteryCurrentGainTemperatureCalibrationShuntTemperature	= defaultEepromData.batteryCurrentGainTemperatureCalibrationShuntTemperature;
  dataToStore->changedData.batteryCurrentGainTemperatureCalibrationChipTemperature	= defaultEepromData.batteryCurrentGainTemperatureCalibrationChipTemperature;
  dataToStore->changedData.batteryCurrentOffsetRefshuntVoltage						= defaultEepromData.batteryCurrentOffsetRefshuntVoltage;
  dataToStore->changedData.batteryCurrentOffsetCommonModeCalibrationVoltage			= defaultEepromData.batteryCurrentOffsetCommonModeCalibrationVoltage;
  dataToStore->changedData.batteryCurrentOffsetCommonModeCompensationFactor			= defaultEepromData.batteryCurrentOffsetCommonModeCompensationFactor;
  dataToStore->changedData.batteryCurrentOffsetTemperatureCompensationFactor		= defaultEepromData.batteryCurrentOffsetTemperatureCompensationFactor;
  dataToStore->changedData.batteryCurrentGainRefCurrent								= defaultEepromData.batteryCurrentGainRefCurrent;
  dataToStore->changedData.batteryCurrentGainTemperatureCompensationShuntFactor		= defaultEepromData.batteryCurrentGainTemperatureCompensationShuntFactor;
  dataToStore->changedData.batteryCurrentGainTemperatureCompensationChipFactor		= defaultEepromData.batteryCurrentGainTemperatureCompensationChipFactor;

  dataToStore->changedData.currentOffset											= defaultEepromData.currentOffset;
  dataToStore->changedData.currentGain												= defaultEepromData.currentGain;

  // AH Counter Parameter
  dataToStore->changedData.cef														= defaultEepromData.cef;
  dataToStore->changedData.peukert													= defaultEepromData.peukert;
  dataToStore->changedData.cellCapacity												= defaultEepromData.cellCapacity;
  dataToStore->changedData.cellEnergy												= defaultEepromData.cellEnergy;
  dataToStore->changedData.iBatFull													= defaultEepromData.iBatFull;
  dataToStore->changedData.tBatFull													= defaultEepromData.tBatFull;
  dataToStore->changedData.uBatFull													= defaultEepromData.uBatFull;
  dataToStore->changedData.uBatEmpty												= defaultEepromData.uBatEmpty;
  dataToStore->changedData.socCalcMode												= defaultEepromData.socCalcMode;
  dataToStore->changedData.cellRatedDischargeTime									= defaultEepromData.cellRatedDischargeTime;

  // Schaltausgänge
  dataToStore->changedData.lvpStart													= defaultEepromData.lvpStart;
  dataToStore->changedData.lvpStop													= defaultEepromData.lvpStop;
  dataToStore->changedData.ovpStart													= defaultEepromData.ovpStart;
  dataToStore->changedData.ovpStop													= defaultEepromData.ovpStop;
  dataToStore->changedData.loadCurrentLimit											= defaultEepromData.loadCurrentLimit;
  dataToStore->changedData.chargeCurrentLimit										= defaultEepromData.chargeCurrentLimit;
  dataToStore->changedData.chargeStopHighTemperatureStart							= defaultEepromData.chargeStopHighTemperatureStart;
  dataToStore->changedData.chargeStopHighTemperatureStop							= defaultEepromData.chargeStopHighTemperatureStop;
  dataToStore->changedData.chargeStopLowTemperatureStart							= defaultEepromData.chargeStopLowTemperatureStart;
  dataToStore->changedData.chargeStopLowTemperatureStop								= defaultEepromData.chargeStopLowTemperatureStop;
  dataToStore->changedData.dischargeStopHighTemperatureStart						= defaultEepromData.dischargeStopHighTemperatureStart;
  dataToStore->changedData.dischargeStopHighTemperatureStop							= defaultEepromData.dischargeStopHighTemperatureStop;
  dataToStore->changedData.dischargeStopLowTemperatureStart							= defaultEepromData.dischargeStopLowTemperatureStart;
  dataToStore->changedData.dischargeStopLowTemperatureStop							= defaultEepromData.dischargeStopLowTemperatureStop;

  dataToStore->changedData.uBatEmptyCompStartTemp									= defaultEepromData.uBatEmptyCompStartTemp;
  dataToStore->changedData.uBatEmptyCompStopTemp									= defaultEepromData.uBatEmptyCompStopTemp;
  dataToStore->changedData.uBatEmptyCompStopVolt									= defaultEepromData.uBatEmptyCompStopVolt;

  dataToStore->changedData.extraDischargeStrom_mA									= defaultEepromData.extraDischargeStrom_mA;
  dataToStore->changedData.dischargeTotalAh											= defaultEepromData.dischargeTotalAh;
  dataToStore->changedData.chargeTotalAh											= defaultEepromData.chargeTotalAh;
  dataToStore->changedData.dischargeTotalWh											= defaultEepromData.dischargeTotalWh;
  dataToStore->changedData.chargeTotalWh											= defaultEepromData.chargeTotalWh;
  dataToStore->changedData.cefW														= defaultEepromData.cefW;
  dataToStore->changedData.onTime													= defaultEepromData.onTime;

  dataToStore->changedData.mAsCounter												= defaultEepromData.mAsCounter;
  dataToStore->changedData.detectedCapacity											= defaultEepromData.detectedCapacity;
  dataToStore->changedData.detectedEnergy											= defaultEepromData.detectedEnergy;
  dataToStore->changedData.mAs_AutoMode												= defaultEepromData.mAs_AutoMode;
  dataToStore->changedData.mWs_AutoMode												= defaultEepromData.mWs_AutoMode;

  // Eeprom Status Infos
  dataToStore->eepromState.writeCounter++;
  dataToStore->eepromState.structureSize = sizeof(eeprom_stored_data_t);
  dataToStore->eepromState.revisionInfo = 0;
  dataToStore->eepromState.firstStartId = CONFIG_ID;


  /****************EEPROM Speichern********************/

  EEPROM_Write(0, 0, (uint8_t*)eepromData, SIZE_OF_DATA_TO_STORE);





  /**************** AUSLESEN_UND_PRÜFEN ********************/

  return EEPROM_readConfig(data);



}


//Werkeinstellung ohne Kalibrierwert Überschreibung
HAL_StatusTypeDef EEPROM_factoryRestore(sys_data_t* data, int resetToDefault)
{
  printf("EEPROM FACTORY RESTORE/UPDATE!\n");

 
 
  eeprom_stored_data_t* dataToStore = (eeprom_stored_data_t*)eepromData;

  EEPROM_readConfig(data);														// Restoring calibration data

  // Offset und Gain
  dataToStore->changedData.currentOffset											= data->s.parameter.batteryCurrentOffset;
  dataToStore->changedData.batteryCurrentOffsetRefTemperatureShunt					= data->s.parameter.batteryCurrentOffsetRefTemperatureShunt;
  dataToStore->changedData.batteryCurrentOffsetRefTemperatureChip					= data->s.parameter.batteryCurrentOffsetRefTemperatureChip;
  dataToStore->changedData.batteryCurrentOffsetRefshuntVoltage						= data->s.parameter.batteryCurrentOffsetRefshuntVoltage;
  dataToStore->changedData.batteryCurrentOffsetCommonModeCalibrationVoltage			= data->s.parameter.batteryCurrentOffsetCommonModeCalibrationVoltage;
  dataToStore->changedData.batteryCurrentOffsetCommonModeCompensationFactor			= data->s.parameter.batteryCurrentOffsetCommonModeCompensationFactor;
  dataToStore->changedData.batteryCurrentOffsetTemperatureCalibrationTemperature	= data->s.parameter.batteryCurrentOffsetTemperatureCalibrationTemperature;
  dataToStore->changedData.batteryCurrentOffsetTemperatureCompensationFactor		= data->s.parameter.batteryCurrentOffsetTemperatureCompensationFactor;
  dataToStore->changedData.currentGain												= data->s.parameter.batteryCurrentGainCorrectionFaktor;
  dataToStore->changedData.batteryCurrentGainRefTempShunt							= data->s.parameter.batteryCurrentGainRefTempShunt;
  dataToStore->changedData.batteryCurrentGainRefTempChip							= data->s.parameter.batteryCurrentGainRefTempChip;
  dataToStore->changedData.batteryCurrentGainRefCurrent								= data->s.parameter.batteryCurrentGainRefCurrent;
  dataToStore->changedData.batteryCurrentGainTemperatureCalibrationShuntTemperature	= data->s.parameter.batteryCurrentGainTemperatureCalibrationShuntTemperature;
  dataToStore->changedData.batteryCurrentGainTemperatureCompensationShuntFactor		= data->s.parameter.batteryCurrentGainTemperatureCompensationShuntFactor;
  dataToStore->changedData.batteryCurrentGainTemperatureCalibrationChipTemperature	= data->s.parameter.batteryCurrentGainTemperatureCalibrationChipTemperature;
  dataToStore->changedData.batteryCurrentGainTemperatureCompensationChipFactor		= data->s.parameter.batteryCurrentGainTemperatureCompensationChipFactor;

  // Schnittstellenparameter
  dataToStore->changedData.baudrate													= defaultEepromData.baudrate;
  dataToStore->changedData.parityMode												= defaultEepromData.parityMode;
  dataToStore->changedData.stopBits													= defaultEepromData.stopBits;
  dataToStore->changedData.slave_adress												= defaultEepromData.slave_adress;
  dataToStore->changedData.ibn_day													= defaultEepromData.ibn_day;
  dataToStore->changedData.ibn_month												= defaultEepromData.ibn_month;
  dataToStore->changedData.ibn_year													= defaultEepromData.ibn_year;
  dataToStore->changedData.user_id													= defaultEepromData.user_id;

  //Ah counter
  dataToStore->changedData.cef														= defaultEepromData.cef;
  dataToStore->changedData.cellCapacity												= defaultEepromData.cellCapacity;
  dataToStore->changedData.cellEnergy												= defaultEepromData.cellEnergy;
  dataToStore->changedData.iBatFull													= defaultEepromData.iBatFull;
  dataToStore->changedData.peukert													= defaultEepromData.peukert;
  dataToStore->changedData.tBatFull													= defaultEepromData.tBatFull;
  dataToStore->changedData.uBatFull													= defaultEepromData.uBatFull;
  dataToStore->changedData.uBatEmpty												= defaultEepromData.uBatEmpty;
  dataToStore->changedData.socCalcMode												= defaultEepromData.socCalcMode;
  dataToStore->changedData.cellRatedDischargeTime									= defaultEepromData.cellRatedDischargeTime;

  // Schaltausgänge
  dataToStore->changedData.lvpStart													= defaultEepromData.lvpStart;
  dataToStore->changedData.lvpStop													= defaultEepromData.lvpStop;
  dataToStore->changedData.ovpStart													= defaultEepromData.ovpStart;
  dataToStore->changedData.ovpStop													= defaultEepromData.ovpStop;
  dataToStore->changedData.loadCurrentLimit											= defaultEepromData.loadCurrentLimit;
  dataToStore->changedData.chargeCurrentLimit										= defaultEepromData.chargeCurrentLimit;
  dataToStore->changedData.chargeStopHighTemperatureStart							= defaultEepromData.chargeStopHighTemperatureStart;
  dataToStore->changedData.chargeStopHighTemperatureStop							= defaultEepromData.chargeStopHighTemperatureStop;
  dataToStore->changedData.chargeStopLowTemperatureStart							= defaultEepromData.chargeStopLowTemperatureStart;
  dataToStore->changedData.chargeStopLowTemperatureStop								= defaultEepromData.chargeStopLowTemperatureStop;
  dataToStore->changedData.dischargeStopHighTemperatureStart						= defaultEepromData.dischargeStopHighTemperatureStart;
  dataToStore->changedData.dischargeStopHighTemperatureStop							= defaultEepromData.dischargeStopHighTemperatureStop;
  dataToStore->changedData.dischargeStopLowTemperatureStart							= defaultEepromData.dischargeStopLowTemperatureStart;
  dataToStore->changedData.dischargeStopLowTemperatureStop							= defaultEepromData.dischargeStopLowTemperatureStop;

  dataToStore->changedData.uBatEmptyCompStartTemp									= defaultEepromData.uBatEmptyCompStartTemp;
  dataToStore->changedData.uBatEmptyCompStopTemp									= defaultEepromData.uBatEmptyCompStopTemp;
  dataToStore->changedData.uBatEmptyCompStopVolt									= defaultEepromData.uBatEmptyCompStopVolt;

  dataToStore->changedData.extraDischargeStrom_mA									= defaultEepromData.extraDischargeStrom_mA;
  dataToStore->changedData.dischargeTotalAh											= defaultEepromData.dischargeTotalAh;
  dataToStore->changedData.chargeTotalAh											= defaultEepromData.chargeTotalAh;
  dataToStore->changedData.cefW														= defaultEepromData.cefW;
  dataToStore->changedData.onTime													= defaultEepromData.onTime;

  // These fields are new
  dataToStore->changedData.mAsCounter												= defaultEepromData.mAsCounter;
  dataToStore->changedData.detectedCapacity											= defaultEepromData.detectedCapacity;
  dataToStore->changedData.detectedEnergy											= defaultEepromData.detectedEnergy;
  dataToStore->changedData.mAs_AutoMode												= defaultEepromData.mAs_AutoMode;
  dataToStore->changedData.mWs_AutoMode												= defaultEepromData.mWs_AutoMode;
  dataToStore->changedData.dischargeTotalWh											= defaultEepromData.dischargeTotalWh;
  dataToStore->changedData.chargeTotalWh											= defaultEepromData.chargeTotalWh;


  dataToStore->eepromState.writeCounter	  = dataToStore->eepromState.writeCounter++;
  dataToStore->eepromState.structureSize  = sizeof(eeprom_stored_data_t);
  dataToStore->eepromState.revisionInfo	  = 0;
  dataToStore->eepromState.firstStartId = CONFIG_ID;

  dataToStore->deviceInfo.deviceInfoWritten	= 1;
  dataToStore->deviceInfo.SN				= data->s.parameter.sn;

  EEPROM_Write(0,0, (uint8_t*)dataToStore, SIZE_OF_DATA_TO_STORE);

 
  return EEPROM_readConfig(data);
}

HAL_StatusTypeDef EEPROM_storeConfig(sys_data_t* data, uint8_t withSN)
{
  eeprom_stored_data_t* dataToStore;
  uint32_t PageError;
  uint32_t Address;
  uint32_t x;
  /****************LESE_WERTE_AUS_SYSDATA*********************/
  printf("EEPROM STORE CONFIG!\n");
  dataToStore = (eeprom_stored_data_t*) eepromData;

  // Schnittstellenparameter
  dataToStore->changedData.baudrate = data->s.parameter.baudrate;
  dataToStore->changedData.parityMode =	data->s.parameter.parityMode;
  dataToStore->changedData.stopBits = data->s.parameter.stopBit;
  dataToStore->changedData.slave_adress = data->s.parameter.slave_address;
  dataToStore->changedData.ibn_day = data->s.parameter.ibn_day;
  dataToStore->changedData.ibn_month = data->s.parameter.ibn_month;
  dataToStore->changedData.ibn_year = data->s.parameter.ibn_year;
  dataToStore->changedData.user_id = data->s.parameter.user_id;

  // Offset und Gain
  dataToStore->changedData.batteryCurrentOffsetRefTemperatureChip = data->s.parameter.batteryCurrentOffsetRefTemperatureChip;
  dataToStore->changedData.batteryCurrentOffsetRefTemperatureShunt = data->s.parameter.batteryCurrentOffsetRefTemperatureShunt;

  dataToStore->changedData.batteryCurrentGainRefTempShunt = data->s.parameter.batteryCurrentGainRefTempShunt;
  dataToStore->changedData.batteryCurrentGainRefTempChip = data->s.parameter.batteryCurrentGainRefTempChip;
  dataToStore->changedData.batteryCurrentOffsetTemperatureCalibrationTemperature = data->s.parameter.batteryCurrentOffsetTemperatureCalibrationTemperature;
  dataToStore->changedData.batteryCurrentGainTemperatureCalibrationShuntTemperature = data->s.parameter.batteryCurrentGainTemperatureCalibrationShuntTemperature;
  dataToStore->changedData.batteryCurrentGainTemperatureCalibrationChipTemperature = data->s.parameter.batteryCurrentGainTemperatureCalibrationChipTemperature;
  dataToStore->changedData.batteryCurrentOffsetRefshuntVoltage = data->s.parameter.batteryCurrentOffsetRefshuntVoltage;

  dataToStore->changedData.batteryCurrentOffsetCommonModeCalibrationVoltage = data->s.parameter.batteryCurrentOffsetCommonModeCalibrationVoltage;
  dataToStore->changedData.batteryCurrentOffsetCommonModeCompensationFactor = data->s.parameter.batteryCurrentOffsetCommonModeCompensationFactor;
  dataToStore->changedData.batteryCurrentOffsetTemperatureCompensationFactor = data->s.parameter.batteryCurrentOffsetTemperatureCompensationFactor;
  dataToStore->changedData.batteryCurrentGainRefCurrent = data->s.parameter.batteryCurrentGainRefCurrent;
  dataToStore->changedData.batteryCurrentGainTemperatureCompensationShuntFactor = data->s.parameter.batteryCurrentGainTemperatureCompensationShuntFactor;
  dataToStore->changedData.batteryCurrentGainTemperatureCompensationChipFactor = data->s.parameter.batteryCurrentGainTemperatureCompensationChipFactor;

  dataToStore->changedData.currentOffset = data->s.parameter.batteryCurrentOffset;
  dataToStore->changedData.currentGain = data->s.parameter.batteryCurrentGainCorrectionFaktor;

  // AH COUNTER Einstellungen
  dataToStore->changedData.cef = data->s.parameter.cef;
  dataToStore->changedData.peukert = data->s.parameter.peukert;
  dataToStore->changedData.cellCapacity = data->s.parameter.cellCapacity;
  dataToStore->changedData.cellEnergy =	data->s.parameter.battEnergy;
  dataToStore->changedData.iBatFull = data->s.parameter.iBatFull;
  dataToStore->changedData.tBatFull = data->s.parameter.tBatFull;
  dataToStore->changedData.uBatFull = data->s.parameter.uBatFull;
  dataToStore->changedData.uBatEmpty = data->s.parameter.uBatEmpty;
  dataToStore->changedData.socCalcMode = data->s.parameter.socCalcMode;

  dataToStore->changedData.cellRatedDischargeTime = data->s.parameter.cellRatedDischargeTime;
  // Schaltausgänge
  dataToStore->changedData.lvpStart = data->s.parameter.lvpStart;
  dataToStore->changedData.lvpStop = data->s.parameter.lvpStop;
  dataToStore->changedData.ovpStart = data->s.parameter.ovpStart;
  dataToStore->changedData.ovpStop = data->s.parameter.ovpStop;
  dataToStore->changedData.loadCurrentLimit = data->s.parameter.loadCurrentLimit;
  dataToStore->changedData.chargeCurrentLimit =	data->s.parameter.chargeCurrentLimit;
  dataToStore->changedData.chargeStopHighTemperatureStart = data->s.parameter.chargeStopHighTemperatureStart;
  dataToStore->changedData.chargeStopHighTemperatureStop = data->s.parameter.chargeStopHighTemperatureStop;
  dataToStore->changedData.chargeStopLowTemperatureStart = data->s.parameter.chargeStopLowTemperatureStart;
  dataToStore->changedData.chargeStopLowTemperatureStop = data->s.parameter.chargeStopLowTemperatureStop;
  dataToStore->changedData.dischargeStopHighTemperatureStart = data->s.parameter.dischargeStopHighTemperatureStart;
  dataToStore->changedData.dischargeStopHighTemperatureStop = data->s.parameter.dischargeStopHighTemperatureStop;
  dataToStore->changedData.dischargeStopLowTemperatureStart = data->s.parameter.dischargeStopLowTemperatureStart;
  dataToStore->changedData.dischargeStopLowTemperatureStop = data->s.parameter.dischargeStopLowTemperatureStop;

  // Neue Parameter für SOC
  dataToStore->changedData.uBatEmptyCompStartTemp = data->s.parameter.uBatEmptyCompStartTemp;
  dataToStore->changedData.uBatEmptyCompStopTemp = data->s.parameter.uBatEmptyCompStopTemp;
  dataToStore->changedData.uBatEmptyCompStopVolt = data->s.parameter.uBatEmptyCompStopVolt;

  dataToStore->changedData.extraDischargeStrom_mA = data->s.parameter.extraDischargeStrom_mA;
  dataToStore->changedData.dischargeTotalAh = data->s.values.dischargeTotalAh;
  dataToStore->changedData.chargeTotalAh = data->s.values.chargeTotalAh;
  dataToStore->changedData.dischargeTotalWh = data->s.values.dischargeTotalWh;
  dataToStore->changedData.chargeTotalWh = data->s.values.chargeTotalWh;
  dataToStore->changedData.cefW = data->s.parameter.cefW;
  dataToStore->changedData.onTime = data->s.values.onTime;

  dataToStore->changedData.mAsCounter = data->s.values.mAsCounter;
  dataToStore->changedData.detectedCapacity = data->s.values.detectedCapacity;
  dataToStore->changedData.detectedEnergy = data->s.values.detectedEnergy;
  dataToStore->changedData.mAs_AutoMode = data->s.values.mAs_AutoMode;
  dataToStore->changedData.mWs_AutoMode = data->s.values.mWs_AutoMode;

  // Eeprom Status Infos
  dataToStore->eepromState.writeCounter++;
  dataToStore->eepromState.structureSize = sizeof(eeprom_stored_data_t);
  dataToStore->eepromState.revisionInfo = 0;
  dataToStore->eepromState.firstStartId = CONFIG_ID;

  if (withSN)
  {
    printf("Writing SN!\n");
    dataToStore->deviceInfo.SN = data->s.parameter.sn;
  }


  EEPROM_Write(0,0, (uint8_t*)dataToStore, SIZE_OF_DATA_TO_STORE);

  return EEPROM_readConfig(data);
}

//------------------------------------------------------------------------------

HAL_StatusTypeDef EEPROM_readConfig(sys_data_t* data)
{
  eeprom_stored_data_t* dataToStore;

  /****************WERTE_AUS_EEPROM_LESEN********************/


  EEPROM_Read(0, 0, (uint8_t*)eepromData,  sizeof(eepromData));


  dataToStore = (eeprom_stored_data_t*)eepromData;

  // Schnittstellenparameter
  data->s.parameter.baudrate													= dataToStore->changedData.baudrate;
  data->s.parameter.parityMode													= dataToStore->changedData.parityMode;
  data->s.parameter.stopBit														= dataToStore->changedData.stopBits;
  data->s.parameter.slave_address												= dataToStore->changedData.slave_adress;
  data->s.parameter.ibn_day														= dataToStore->changedData.ibn_day;
  data->s.parameter.ibn_month													= dataToStore->changedData.ibn_month;
  data->s.parameter.ibn_year													= dataToStore->changedData.ibn_year;
  data->s.parameter.user_id														= dataToStore->changedData.user_id;

  // Offset und Gain
  data->s.parameter.batteryCurrentOffsetRefTemperatureShunt						= dataToStore->changedData.batteryCurrentOffsetRefTemperatureShunt;
  data->s.parameter.batteryCurrentOffsetRefTemperatureChip						= dataToStore->changedData.batteryCurrentOffsetRefTemperatureChip;
  data->s.parameter.batteryCurrentGainRefTempShunt								= dataToStore->changedData.batteryCurrentGainRefTempShunt;
  data->s.parameter.batteryCurrentGainRefTempChip								= dataToStore->changedData.batteryCurrentGainRefTempChip;
  data->s.parameter.batteryCurrentOffsetTemperatureCalibrationTemperature		= dataToStore->changedData.batteryCurrentOffsetTemperatureCalibrationTemperature;
  data->s.parameter.batteryCurrentGainTemperatureCalibrationShuntTemperature	= dataToStore->changedData.batteryCurrentGainTemperatureCalibrationShuntTemperature;
  data->s.parameter.batteryCurrentGainTemperatureCalibrationChipTemperature		= dataToStore->changedData.batteryCurrentGainTemperatureCalibrationChipTemperature;
  data->s.parameter.batteryCurrentOffsetRefshuntVoltage							= dataToStore ->changedData.batteryCurrentOffsetRefshuntVoltage;
  data->s.parameter.batteryCurrentOffsetCommonModeCalibrationVoltage			= dataToStore->changedData.batteryCurrentOffsetCommonModeCalibrationVoltage;
  data->s.parameter.batteryCurrentOffsetCommonModeCompensationFactor			= dataToStore->changedData.batteryCurrentOffsetCommonModeCompensationFactor;
  data->s.parameter.batteryCurrentOffsetTemperatureCompensationFactor			= dataToStore->changedData.batteryCurrentOffsetTemperatureCompensationFactor;
  data->s.parameter.batteryCurrentGainRefCurrent								= dataToStore->changedData.batteryCurrentGainRefCurrent;
  data->s.parameter.batteryCurrentGainTemperatureCompensationShuntFactor		= dataToStore->changedData.batteryCurrentGainTemperatureCompensationShuntFactor;
  data->s.parameter.batteryCurrentGainTemperatureCompensationChipFactor			= dataToStore->changedData.batteryCurrentGainTemperatureCompensationChipFactor;
  data->s.parameter.batteryCurrentOffset										= dataToStore->changedData.currentOffset;
  data->s.parameter.batteryCurrentGainCorrectionFaktor							= dataToStore->changedData.currentGain;

  //Einstellungenm für AH counter
  data->s.parameter.cef															= dataToStore ->changedData.cef;
  data->s.parameter.peukert														= dataToStore ->changedData.peukert;
  data->s.parameter.cellCapacity												= dataToStore ->changedData.cellCapacity;
  data->s.parameter.battEnergy													= dataToStore ->changedData.cellEnergy;
  data->s.parameter.iBatFull													= dataToStore ->changedData.iBatFull;
  data->s.parameter.tBatFull													= dataToStore->changedData.tBatFull;
  data->s.parameter.uBatFull													= dataToStore->changedData.uBatFull;
  data->s.parameter.uBatEmpty													= dataToStore->changedData.uBatEmpty;
  data->s.parameter.socCalcMode													= dataToStore->changedData.socCalcMode;
  data->s.parameter.cellRatedDischargeTime										= dataToStore->changedData.cellRatedDischargeTime;

  // New EU directive says that cell Energy in Wh must be somwhere on the
  // visible part of the cell as well as capacity in Ah


  // Schaltausgänge
  data->s.parameter.lvpStart													= dataToStore->changedData.lvpStart;
  data->s.parameter.lvpStop														= dataToStore->changedData.lvpStop;
  data->s.parameter.ovpStart													= dataToStore->changedData.ovpStart;
  data->s.parameter.ovpStop														= dataToStore->changedData.ovpStop;
  data->s.parameter.loadCurrentLimit											= dataToStore->changedData.loadCurrentLimit;
  data->s.parameter.chargeCurrentLimit											= dataToStore->changedData.chargeCurrentLimit;
  data->s.parameter.chargeStopHighTemperatureStart								= dataToStore->changedData.chargeStopHighTemperatureStart;
  data->s.parameter.chargeStopHighTemperatureStop								= dataToStore->changedData.chargeStopHighTemperatureStop;
  data->s.parameter.chargeStopLowTemperatureStart								= dataToStore->changedData.chargeStopLowTemperatureStart;
  data->s.parameter.chargeStopLowTemperatureStop								= dataToStore->changedData.chargeStopLowTemperatureStop;
  data->s.parameter.dischargeStopHighTemperatureStart							= dataToStore->changedData.dischargeStopHighTemperatureStart;
  data->s.parameter.dischargeStopHighTemperatureStop							= dataToStore->changedData.dischargeStopHighTemperatureStop;
  data->s.parameter.dischargeStopLowTemperatureStart							= dataToStore->changedData.dischargeStopLowTemperatureStart;
  data->s.parameter.dischargeStopLowTemperatureStop								= dataToStore->changedData.dischargeStopLowTemperatureStop;

  data->s.parameter.uBatEmptyCompStartTemp										= dataToStore->changedData.uBatEmptyCompStartTemp;
  data->s.parameter.uBatEmptyCompStopTemp										= dataToStore->changedData.uBatEmptyCompStopTemp;
  data->s.parameter.uBatEmptyCompStopVolt										= dataToStore->changedData.uBatEmptyCompStopVolt;

  data->s.parameter.extraDischargeStrom_mA										= dataToStore->changedData.extraDischargeStrom_mA;
  data->s.values.dischargeTotalAh												= dataToStore->changedData.dischargeTotalAh;
  data->s.values.chargeTotalAh													= dataToStore->changedData.chargeTotalAh;
  data->s.values.dischargeTotalWh												= dataToStore->changedData.dischargeTotalWh;
  data->s.values.chargeTotalWh													= dataToStore->changedData.chargeTotalWh;
  data->s.parameter.cefW														= dataToStore ->changedData.cefW;
  data->s.values.onTime															= dataToStore->changedData.onTime;

  data->s.values.mAsCounter														= dataToStore->changedData.mAsCounter;
  data->s.values.detectedCapacity												= dataToStore->changedData.detectedCapacity;
  data->s.values.detectedEnergy													= dataToStore->changedData.detectedEnergy;
  data->s.values.mAs_AutoMode													= dataToStore->changedData.mAs_AutoMode;
  data->s.values.mWs_AutoMode													= dataToStore->changedData.mWs_AutoMode;

  //  Geräteinformation
  data->s.parameter.sn															= dataToStore->deviceInfo.SN;

  // prüfe Eeprom Status Infos
  //dataToStore->eepromState.writeCounter ++ ;
  if (dataToStore->eepromState.structureSize != sizeof(eeprom_stored_data_t)) return HAL_ERROR;
  if (dataToStore->eepromState.revisionInfo != 0) return HAL_ERROR;
  if (dataToStore->eepromState.firstStartId != CONFIG_ID) return HAL_ERROR;

  return HAL_OK;
}

//--- NEW Functions
// function to determine the remaining bytes
uint16_t bytestowrite (uint16_t size, uint16_t offset)
{
	if ((size+offset)<PAGE_SIZE) return size;
	else return PAGE_SIZE-offset;
}


void EEPROM_Read (uint16_t page, uint16_t offset, uint8_t *data, uint16_t size)
{
	int paddrposition = log(PAGE_SIZE)/log(2);

	uint16_t startPage = page;
	uint16_t endPage = page + ((size+offset)/PAGE_SIZE);

	uint16_t numofpages = (endPage-startPage) + 1;
	uint16_t pos=0;

	for (int i=0; i<numofpages; i++)
	{
		uint16_t MemAddress = startPage<<paddrposition | offset;
		uint16_t bytesremaining = bytestowrite(size, offset);
		HAL_I2C_Mem_Read(EEPROM_I2C, EEPROM_ADDR, MemAddress, 2, &data[pos], bytesremaining, 1000);
		startPage += 1;
		offset=0;
		size = size-bytesremaining;
		pos += bytesremaining;
	}
}


void EEPROM_Write (uint16_t page, uint16_t offset, uint8_t *data, uint16_t size)
{

	// Find out the number of bit, where the page addressing starts
	int paddrposition = log(PAGE_SIZE)/log(2);

	// calculate the start page and the end page
	uint16_t startPage = page;
	uint16_t endPage = page + ((size+offset)/PAGE_SIZE);

	// number of pages to be written
	uint16_t numofpages = (endPage-startPage) + 1;
	uint16_t pos=0;

	// write the data
	for (int i=0; i<numofpages; i++)
	{
		/* calculate the address of the memory location
		 * Here we add the page address with the byte address
		 */
		uint16_t MemAddress = startPage<<paddrposition | offset;
		uint16_t bytesremaining = bytestowrite(size, offset);  // calculate the remaining bytes to be written

		HAL_I2C_Mem_Write(EEPROM_I2C, EEPROM_ADDR, MemAddress, 2, &data[pos], bytesremaining, 1000);  // write the data to the EEPROM

		startPage += 1;  // increment the page, so that a new page address can be selected for further write
		offset=0;   // since we will be writing to a new page, so offset will be 0
		size = size-bytesremaining;  // reduce the size of the bytes
		pos += bytesremaining;  // update the position for the data buffer

		HAL_Delay (5);  // Write cycle delay (5ms)
	}
}
