/**
  ******************************************************************************
  * @file    balancer.c
  * @author  ECS, Falko Jahn
  * @version V1.0.0
  * @date    03.02.2021
  * @brief   BALANCER Modul 
  *          Beschreibung in Header
  ******************************************************************************
  */ 

// --- INCLUDES ----------------------------------------------------------------
#include <stdio.h>
#include "balancer.h"
#include "main.h"
#include "sysdata.h"
#include "tim.h"
#include "dac.h"
#include "comp.h"
#include "led.h"


//--- GGF. EXTERNE VARIABLEN ---------------------------------------------------  

//--- LOKALE DEFINES - bitte hier dokumentieren --------------------------------
//Imax = 20A
//Verstrkung = 100
//Shunt = 0,001 Ohm
//U dac =  Imax * Rshunt * Verstrkung --> 20 A * 0,001 Ohm * 100 = 2.0V
//Dac Value = Udac / (Uref / 4096)
//#define MAX_DAC_VALUE 3276
//Zur Zeit reduzieren wir den max. Wert weil der Strommessverstrker langsam ist und zu spt den max Wert ausgibt
//Daher zur Zeit nur 1,7V statt 2.0V
#define MAX_DAC_VALUE 1500  //2300

//MAX Timer Value um nicht mehr laufenden DC DC Wandler zu erkennen
//gemessen 1500 Periode bei 5V/12 und Sysclock 64Mhz
//um Faktor 10 vergrert
#define MAX_TIMER_VALUE 500  



#define MIN_OUTPUT_VOLTAGE        10000     //mV
#define MAX_OUTPUT_VOLTAGE        68000     //mv //Messgenauikeit ca. +- 2-3V
#define MAX_ERROR                 100       //
#define RESTART_TIMEOUT           100       //ms
#define BALANCER_REGULATION_TIME  10        //Alle 10mS ein Schritt
#define CONVERTER_MIN_POWER       300       //300 von 3000 = 10%
//--- LOKALE TYPE DEFS - bitte hier dokumentieren-------------------------------

//--- DEFINATIONEN GLOBALER VARIABLEN - Bitte in Header dokumentieren ----------

//--- LOKALE VARIABLEN - bitte hier dokumentieren ------------------------------

uint32_t restartCounter;
uint32_t startImpulsCounter;
uint32_t balancer_running;
uint32_t secondCounter;
uint32_t balancerRegulationCounter= BALANCER_REGULATION_TIME; 
//--- LOKALE FUNKTIONS PROTOTYPEN ---------------------------------------------- 
void BALANCER_SetStartImpulse(void);    

//--- LOKALE FUNKTIONEN - bitte hier dokumentieren -----------------------------

//--- GLOBALE FUNKTIONEN - bitte in Header dokumentieren------------------------
void BALANCER_Init(void)
{
  
  // Starte timer zur Messung der Charge Time und der Charge Transfer Time
  // Charge Time bedeutet die Zeit zum Aufbau des Magnedfeldes. Also vom Einschalten
  // des Mosfets bis zum erreichen der Maximal Stroms.
  //HAL_TIM_Base_Start_IT(&htim16);  
  //HAL_TIM_Base_Start_IT(&htim17);

  HAL_TIM_IC_Start(&htim1,TIM_CHANNEL_1);
  HAL_TIM_IC_Start(&htim1,TIM_CHANNEL_2);





  if (HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0) != HAL_OK)
  {
    /* Setting value Error */
    printf("HAL_DAC_SetValue ERROR\n");
    return;
  }
  printf("HAL_DAC_SetValue OK\n");


  if (HAL_DAC_Start(&hdac1, DAC_CHANNEL_1) != HAL_OK)
  {
    /* Start Error */
    printf("HAL_DAC_Start ERROR\n");
    return;
  }
  printf("HAL_DAC_Start OK\n");


  //Comparator fr Strom
  if(HAL_COMP_Start(&hcomp1) != HAL_OK)
  {
    /* Initialization Error */
    printf("HAL_COMP1_Start ERROR\n");
    return;
  }
  printf("HAL_COMP1_Start OK\n");
  

  //Comparator fr Charge Transfer
  if(HAL_COMP_Start(&hcomp2) != HAL_OK)
  {
    /* Initialization Error */
    printf("HAL_COMP2_Start ERROR\n");
    return;
  }
  printf("HAL_COMP2_Start OK\n");
  printf("BALANCER_Init OK\n");

}
uint32_t counterValue;

void BALANCER_Exec()
{
  uint32_t val1 = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);
  uint32_t val2 = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_2);
  

  //Val1 representiert die gesamte Periode von Ipeak Abschaltung zu Ipeak Abschaltung (falling edge comparator 1)
  //Val2 Periode von Ipeak Abschaltung (falling edge comparator 1) bis zu ende charge transfer (comparartor 2 rising edge )
  uint32_t periodeTime = val1;
  uint32_t chargeTransferTime = val2;
  uint32_t chargeTime = periodeTime - chargeTransferTime;
  uint32_t trafo = 2;// n2 / n1;
  uint32_t usek = ((float)chargeTime / (float)chargeTransferTime) * trafo * sysData.s.cellVoltage;
  sysData.s.chargeTime = chargeTime;
  sysData.s.chargeTransferTime = chargeTransferTime;
  sysData.s.sekVoltage = usek / 10;
  

  //Wenn Balancer eingeschaltet
  if (sysData.s.balancerPower > 0) 
  {
    // ----- Prfe ob  Flyback converter luft -----
    counterValue = __HAL_TIM_GET_COUNTER(&htim1);
    if (( counterValue > MAX_TIMER_VALUE) && (sysData.s.converterError == CONVERTER_ERROR_NONE)  )
    {
        restartCounter++;  
        balancer_running=0;
    }
    else
    {
      if (restartCounter>0) restartCounter--;  
    }


    if (restartCounter >= RESTART_TIMEOUT)
    {
          BALANCER_SetStartImpulse();
          restartCounter = 0;
          balancer_running=1;
          startImpulsCounter++;
    }    
    else
    {

    }

    if (startImpulsCounter > 10)
    {
      sysData.s.balancerPower=0;      
      HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0);
      sysData.s.converterError = CONVERTER_ERROR_STARTUP_ERROR;
      printf("CONVERTER ERROR: CONVERTER_STARTUP ERROR!\n");
      startImpulsCounter = 0;

    }

    
    secondCounter++;
    if (secondCounter > 999)
    {
      if (startImpulsCounter > 0)  startImpulsCounter--;
      secondCounter = 0;
    }
   


    // ----- Prfe ob  Flyback converter Ausgangsspannung zu hoch -----
    if  ((usek > MAX_OUTPUT_VOLTAGE) && (balancer_running == 1))
    {
      sysData.s.SekHvErrorCounter++;
    }
    else
    {
      if (sysData.s.SekHvErrorCounter>0) sysData.s.SekHvErrorCounter--;
    }

    if (sysData.s.SekHvErrorCounter > MAX_ERROR)
    {
      sysData.s.balancerPower=0;      
      HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0);
      sysData.s.converterError = CONVERTER_ERROR_OUTPUT_VOLT_TOO_HIGH;
      printf("CONVERTER ERROR: CONVERTER_ERROR_OUTPUT_VOLT_TOO_HIGH\n");
      sysData.s.SekHvErrorCounter=0;
    }

    // ----- Prfe ob  Flyback converter Ausgangsspannung zu niedrig -----
    if  ((usek < MIN_OUTPUT_VOLTAGE) && (balancer_running == 1))
    {
      sysData.s.SekLvErrorCounter++;
    }
    else
    {
      if (sysData.s.SekLvErrorCounter>0) sysData.s.SekLvErrorCounter--;
    }

    if (sysData.s.SekLvErrorCounter > MAX_ERROR)
    {
      sysData.s.balancerPower=0;
      HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0);
      sysData.s.converterError = CONVERTER_ERROR_OUTPUT_VOLT_TOO_LOW;
      printf("CONVERTER ERROR: CONVERTER_ERROR_OUTPUT_VOLT_TOO_LOW\n");
      sysData.s.SekLvErrorCounter=0;
    }
  }
  else
  {
    //Balancer ist ausgeschaltet
    sysData.s.sekVoltage=0;
  }

  if (balancerRegulationCounter > 0) balancerRegulationCounter--;

  if ((sysData.s.mode == 0) && (balancerRegulationCounter == 0)) //AUTO MODE
  {	
    balancerRegulationCounter = BALANCER_REGULATION_TIME;
    if (sysData.s.cellVoltageUnfiltered > sysData.s.balancerVoltage)
    {     
      if ((sysData.s.balancerPower < MAX_DAC_VALUE) && (sysData.s.converterError ==  CONVERTER_ERROR_NONE ))
      {
        sysData.s.balancerPower++;
        if (sysData.s.balancerPower < CONVERTER_MIN_POWER ) 
        {
          sysData.s.balancerPower = CONVERTER_MIN_POWER;
          startImpulsCounter = 0;
        }
        HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sysData.s.balancerPower);
      }
    }
    if (sysData.s.cellVoltageUnfiltered < sysData.s.balancerVoltage)
    {
      if (sysData.s.balancerPower > 0) 
      {
        sysData.s.balancerPower--;
        if( sysData.s.balancerPower < CONVERTER_MIN_POWER) sysData.s.balancerPower = 0;
        HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sysData.s.balancerPower);

      }
    } 
  }

  if (sysData.s.mode == 1) 
  {
    if ((sysData.s.balancerPower < MAX_DAC_VALUE) && (sysData.s.converterError ==  CONVERTER_ERROR_NONE ))
    {
      HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, sysData.s.balancerPower);
    }
  }


  
  if (sysData.s.balancerPower > 0)
  {
    LED_FunctionSetTimes(900,100);
  }
  else
  {
    LED_FunctionSetTimes(100,900);
  }


}




void BALANCER_SetStartImpulse()
{
   
      //Balancer arbeitet nicht. Schalte Ausgang von Comparator um auf normalen GPIO, 
      //setze ausgang auf 0, und schalte dann wieder auf Comparator, dadurch wird ein neuer Setz Impuls auf das Flip Flop gegeben.
      printf("DC DC Wandler not running, start impuls\n");
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      GPIO_InitStruct.Pin = COMP2_OUT_DISCHARGE_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(COMP2_OUT_DISCHARGE_GPIO_Port, &GPIO_InitStruct);
      HAL_GPIO_WritePin(COMP2_OUT_DISCHARGE_GPIO_Port, COMP2_OUT_DISCHARGE_Pin, GPIO_PIN_RESET);

      //Ausgang zurck auf Comparator
      GPIO_InitStruct.Pin = COMP2_OUT_DISCHARGE_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      GPIO_InitStruct.Alternate = GPIO_AF7_COMP2;
      HAL_GPIO_Init(COMP2_OUT_DISCHARGE_GPIO_Port, &GPIO_InitStruct);

}