/******************************************************************************
*
* @file    outputs.c
* @author  ECS, Falko Jahn
* @version V1.0.0
* @date    2020-05-01
* @brief       
*
******************************************************************************/

//--- INCLUDES -----------------------------------------------------------------
#include "outputs.h"
#include "main.h"
#include "stdio.h"
#include "sysdata.h"
//--- EXTERNE VARIABLEN -------------------------------------------------------- 

//--- LOKALE DEFINES - bitte hier dokumentieren --------------------------------

//--- LOKALE TYPE DEFS - bitte hier dokumentieren-------------------------------

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

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

//--- LOKALE FUNKTIONS PROTOTYPEN ---------------------------------------------- 
/*
* @brief
* @param	kein
* @retval	kein
*/
//--- LOKALE FUNKTIONEN - bitte hier dokumentieren -----------------------------



//	--- GLOBALE FUNKTIONEN - bitte in Header dokumentieren------------------------
void OUTPUTS_Init(void)
{
  sys_data.s.values.lvpState = OUTPUTS_LVP_UNKNOWN;
  sys_data.s.values.ovpState = OUTPUTS_OVP_UNKNOWN;

}

/*
* @brief        Prüfen ob LVP Signal abgeschaltet werden muss
*               LVP Signal kommt vom BMS und schaltet die Lasten ab. Wird hier auch abgeschaltet wenn der Laststrom zu hoch ist,
*               oder wenn die Geräte Temperatur zu hoch oder zu niedrig ist. 
* @param	kein
* @retval	kein
*/
void OUTPUTS_CheckLVP(void)
{
	static uint16_t lastMode;

	if (sys_data.s.parameter.lvpMode == OUTPUTS_LVP_MODE_AUTO)
	{
		if (lastMode != OUTPUTS_LVP_MODE_AUTO)
		{
			sys_data.s.values.lvpState = OUTPUTS_LVP_UNKNOWN;
		}

		if ((sys_data.s.values.lvpState == OUTPUTS_LVP_OK) || (sys_data.s.values.lvpState == OUTPUTS_LVP_UNKNOWN))
		{
			if(sys_data.s.values.batteryVoltage < sys_data.s.parameter.lvpStart)
			{
				printf("OUTPUTS_LVP_BATTERY_UNDERVOLTAGE\n");
				sys_data.s.values.lvpState = OUTPUTS_LVP_BATTERY_UNDERVOLTAGE;
				HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.batteryCurrent < ((int32_t)sys_data.s.parameter.loadCurrentLimit*1000))
			{
				printf("OUTPUTS_LVP_OVERCURRENT\n");
				sys_data.s.values.lvpState = OUTPUTS_LVP_OVERCURRENT;
				HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.shuntTemperature > sys_data.s.parameter.dischargeStopHighTemperatureStart)
			{
				printf("OUTPUTS_LVP_SHUNT_OVERTEMPERATURE\n");
				sys_data.s.values.lvpState = OUTPUTS_LVP_SHUNT_OVERTEMPERATURE;
				HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.chipTemperature > sys_data.s.parameter.dischargeStopHighTemperatureStart)
			{
				printf("OUTPUTS_LVP_CHIP_OVERTEMPERATURE\n");
				sys_data.s.values.lvpState = OUTPUTS_LVP_CHIP_OVERTEMPERATURE;
				HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.shuntTemperature < sys_data.s.parameter.dischargeStopLowTemperatureStart)
			{
				printf("OUTPUTS_LVP_SHUNT_UNDERTEMPERATURE\n");
				sys_data.s.values.lvpState = OUTPUTS_LVP_SHUNT_UNDERTEMPERATURE;
				HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.chipTemperature < sys_data.s.parameter.dischargeStopLowTemperatureStart)
			{
				printf("OUTPUTS_LVP_CHIP_OVERTEMPERATURE\n");
				sys_data.s.values.lvpState = OUTPUTS_LVP_CHIP_UNDERTEMPERATURE;
				HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);
			}
		}

		if ((sys_data.s.values.lvpState != OUTPUTS_LVP_OK) &&
			(sys_data.s.values.batteryVoltage > sys_data.s.parameter.lvpStop) &&
			(sys_data.s.values.batteryCurrent > ((int32_t)sys_data.s.parameter.loadCurrentLimit * 1000)) &&
			(sys_data.s.values.shuntTemperature < sys_data.s.parameter.dischargeStopHighTemperatureStop) &&
			(sys_data.s.values.chipTemperature < sys_data.s.parameter.dischargeStopHighTemperatureStop) &&
			(sys_data.s.values.shuntTemperature > sys_data.s.parameter.dischargeStopLowTemperatureStop) &&
			(sys_data.s.values.chipTemperature > sys_data.s.parameter.dischargeStopLowTemperatureStop))
		{
			//Abschaltkriterien für LVP liegen nicht mehr vor
			//Wenn Abschaltung aufgrund zu hohem Lade/Lastrom erfolgt ist, muss Fehler durch Geräte Reset zurück gesetzt werden
			//Andere Fehler automatisches Reset, wenn Fehler nicht mehr vorliegt.
			//Kunde könnte automatische Reset verhindern, indem er die Stop Werte anders programmiert
			//z.B. 
			//Temperabschaltung Start 80°C
			//Temperaturabschaltung Stop -99°C
			if (sys_data.s.values.lvpState != OUTPUTS_LVP_OVERCURRENT)
			{
				//Andere Fehler, automatisches zurücksetzen, wenn keine Fehlerbedingungen mehr vorliegen
				printf("OUTPUT LVP OK\n");
				sys_data.s.values.lvpState = OUTPUTS_LVP_OK;
				HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_ALLOWED);
			}
		}
	}
	else if (sys_data.s.parameter.lvpMode == OUTPUTS_LVP_MODE_MANUAL_ON)
	{
		HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_ALLOWED);
	}
	else if (sys_data.s.parameter.lvpMode == OUTPUTS_LVP_MODE_MANUAL_OFF)
	{
		HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);
	}
	else HAL_GPIO_WritePin(LVP_ENABLE_GPIO_Port, LVP_ENABLE_Pin, OUTPUTS_DISCHARGE_NOT_ALLOWED);

	lastMode = sys_data.s.parameter.lvpMode;
}

/*
* @brief        Prüfen ob OVP Signal abgeschaltet werden muss
*               OVP Signal kommt vom BMS und schaltet die Ladequellen ab. Wird hier auch abgeschaltet wenn der Ladestrom zu hoch ist,
*               oder wenn die Geräte Temperatur zu hoch oder zu niedrig ist. 
* @param	kein
* @retval	kein
*/
void OUTPUTS_CheckOVP(void)
{
	static uint16_t lastMode;

	if (sys_data.s.parameter.ovpMode == OUTPUTS_OVP_MODE_AUTO)
	{
		if (lastMode != OUTPUTS_OVP_MODE_AUTO)
		{
			sys_data.s.values.ovpState = OUTPUTS_OVP_UNKNOWN;
		}

		if ((sys_data.s.values.ovpState == OUTPUTS_OVP_OK) || (sys_data.s.values.ovpState == OUTPUTS_OVP_UNKNOWN))
		{
			if(sys_data.s.values.batteryVoltage > sys_data.s.parameter.ovpStart)
			{
				printf("OUTPUTS_OVP_BATTERY_OVERVOLTAGE\n");
				sys_data.s.values.ovpState = OUTPUTS_OVP_BATTERY_OVERVOLTAGE;
				HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.batteryCurrent > ((int32_t) sys_data.s.parameter.chargeCurrentLimit * 1000))
			{
				printf("OUTPUTS_OVP_OVERCURRENT\n");
				sys_data.s.values.ovpState = OUTPUTS_OVP_OVERCURRENT;
				HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.shuntTemperature > sys_data.s.parameter.chargeStopHighTemperatureStart)
			{
				printf("OUTPUTS_OVP_SHUNT_OVERTEMPERATURE\n");
				sys_data.s.values.ovpState = OUTPUTS_OVP_SHUNT_OVERTEMPERATURE;
				HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.chipTemperature > sys_data.s.parameter.chargeStopHighTemperatureStart)
			{
				printf("OUTPUTS_OVP_CHIP_OVERTEMPERATURE\n");
				sys_data.s.values.ovpState = OUTPUTS_OVP_CHIP_OVERTEMPERATURE;
				HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.shuntTemperature < sys_data.s.parameter.chargeStopLowTemperatureStart)
			{
				printf("OUTPUTS_OVP_SHUNT_UNDERTEMPERATURE\n");
				sys_data.s.values.ovpState = OUTPUTS_OVP_SHUNT_UNDERTEMPERATURE;
				HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);
			}
			else if(sys_data.s.values.chipTemperature < sys_data.s.parameter.chargeStopLowTemperatureStart)
			{
				printf("OUTPUTS_OVP_CHIP_UNDETEMPERATURE\n");
				sys_data.s.values.ovpState = OUTPUTS_OVP_CHIP_UNDERTEMPERATURE;
				HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);
			}
		}

		if ((sys_data.s.values.ovpState != OUTPUTS_OVP_OK) &&
			(sys_data.s.values.batteryVoltage < sys_data.s.parameter.ovpStop) &&
			(sys_data.s.values.batteryCurrent < ( (int32_t) sys_data.s.parameter.chargeCurrentLimit*1000)) &&
			(sys_data.s.values.shuntTemperature < sys_data.s.parameter.chargeStopHighTemperatureStop) &&
			(sys_data.s.values.chipTemperature < sys_data.s.parameter.chargeStopHighTemperatureStop) &&
			(sys_data.s.values.shuntTemperature > sys_data.s.parameter.chargeStopLowTemperatureStop) &&
			(sys_data.s.values.chipTemperature > sys_data.s.parameter.chargeStopLowTemperatureStop))
		{
			//Abschaltkriterien für OVP liegen nicht mehr vor
			//Wenn Abschaltung aufgrund zu hohem Lade/Lastrom erfolgt ist, dann muss Rücksetzen durch Reset Button erfolgen 
			//Andere Fehler, automatisches zurücksetzen, wenn keine Fehlerbedingungen mehr vorliegen
			if (sys_data.s.values.ovpState != OUTPUTS_OVP_OVERCURRENT)
			{
				printf("OUTPUT OVP OK\n");
				sys_data.s.values.ovpState = OUTPUTS_OVP_OK;
				HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_ALLOWED);
			}
		}
	}
	else if (sys_data.s.parameter.ovpMode == OUTPUTS_OVP_MODE_MANUAL_ON)
	{
		HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_ALLOWED);
	}
	else if (sys_data.s.parameter.ovpMode == OUTPUTS_OVP_MODE_MANUAL_OFF)
	{
		HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);
	}
	else HAL_GPIO_WritePin(OVP_ENABLE_GPIO_Port, OVP_ENABLE_Pin, OUTPUTS_CHARGE_NOT_ALLOWED);

	lastMode = sys_data.s.parameter.ovpMode;
}
/*************************** End of file ****************************/