
#include "sysdata.h"
#include "self_discharge.h"

#define HOLD_TIME   ( 3 * 3600 ) // 3 stunde
#define SD_FILTER 64

int16_t SELF_DISCHARGE_Exec(void)
{

  const double batt_float_voltage_tol = 0.03;
  const double batt_voltage_holding_tol = 10;
  int32_t max_u = sys_data.s.parameter.uBatFull * ( 1 + batt_float_voltage_tol);
  int32_t min_u = sys_data.s.parameter.uBatFull * ( 1 - batt_float_voltage_tol);
  static uint32_t holding_counter = 0;
  static int32_t  u_hold = 0;


  sys_data.s.values.selfDischargeTime = holding_counter;

  int32_t u = sys_data.s.values.batteryVoltage;

  if (u > max_u) 
  {
    u_hold = 0;
    holding_counter = 0;
    return -1;
  }

  if (u < min_u) 
  {
    u_hold = 0;
    holding_counter = 0;
    return -1;
  }

  //Bin im richtigen Spannungsbereich, zu haltende Spannung speichern
  if (u_hold == 0)
  {
    u_hold = u;
  }

  int32_t u_hold_max = u_hold + batt_voltage_holding_tol;
  int32_t u_hold_min = u_hold - batt_voltage_holding_tol;

  if (u > u_hold_max)
  {
    u_hold = 0;
    holding_counter = 0;
    return -2;
  }


  if (u < u_hold_min)
  {
    u_hold = 0;
    holding_counter = 0;
    return -2;
  }

  holding_counter++;
  if (holding_counter > HOLD_TIME)
  {
    sys_data.s.values.selfDischarge = sys_data.s.values.batteryCurrent;
  }



  // --- Mittelwert --- 
  static uint32_t last_days;
  static unsigned long avgsum = 0;

  // Converting seconds into days
  uint32_t days = sys_data.s.values.onTime / (24U * 3600U);

  // Alle 24 Stunden ein Wert zur Mittelwertberechnung hinzufügen
  if (days != last_days)
  {
    last_days = days;
    
    uint32_t avgval;
    // Filterlängen in 2er-Potenzen --> Compiler optimiert 
    avgsum -= avgsum/SD_FILTER;
    avgsum += sys_data.s.values.selfDischarge;
    avgval = avgsum / SD_FILTER;

    sys_data.s.values.selfDischargeAvg = avgval;
  }



  
 
  return 0;


}