/******************************************************************************
*
* @file    chipTemperature.c
* @author  ECS, Joseph Zimmer
* @version V1.0.0
* @date    24-04-2019
* @brief
*
******************************************************************************/

//	--- INCLUDES -----------------------------------------------------------------
#include <stdio.h>
//#include <stdlib.h>
#include "chip_temperature.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 ------------------------------
uint32_t calTemperatureSensor30Value;  // Kalibrierungswert für den Temperatursensor auf dem STM32G0 (Werksmäßig im SCB Bereich gespeichert wird beim Programmstart ausgelesen)
uint32_t calTemperatureSensor130Value; // Kalibrierungswert für den Temperatursensor auf dem STM32G0 (Werksmäßig im SCB Bereich gespeichert wird beim Programmstart ausgelesen)
uint32_t calTemperatureSensorDiff;     // Differenz calTemperatureSensor130Value und calTemperatureSensor30Value wird für die Kalibrierung des internen Temperatursensors bentigt
                                                              // Daten Temperaturanzeige µProzessor

//	--- LOKALE FUNKTIONS PROTOTYPEN ----------------------------------------------

void calc_temp_compensation(void);
int16_t y(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x);

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

/*
* @brief
* @param	kein
* @retval	kein
*/

//	--- GLOBALE FUNKTIONEN - bitte in Header dokumentieren------------------------
void CHIP_TEMPERATURE_Calibration(void)
{
  uint16_t * pCalibrationData;
  float calibrationData30;
  float calibrationData130;

  // lade Temperatur Kalibrierungswert (Wert bei 30°C)
  pCalibrationData = (uint16_t *)TEMPSENSOR_CAL1_ADDR;
  calibrationData30  = * pCalibrationData;


  //Berechnung Spannung in mV bei CAL Punk 30°C
  //Kalbibrierung wurde mit 12 Bit und 3000mV Vref durchgeführt
  calibrationData30 = calibrationData30 / 4096;
  calTemperatureSensor30Value = calibrationData30 * 3000 ;      // jetzt haben wir die Kalibrierungsspannung in Volt bei 30°C;

  pCalibrationData = (uint16_t *)TEMPSENSOR_CAL2_ADDR;
  calibrationData130  = * pCalibrationData;

  //Berechnung Spannung in mV bei CAL Punk 130°C
  //Kalbibrierung wurde mit 12 Bit und 3000mV Vref durchgeführt
  calibrationData130 = calibrationData130 / 4096;
  calTemperatureSensor130Value = calibrationData130 * 3000;      // jetzt haben wir die Kalibrierungsspannung in Volt bei 130°C;

  // Spannungsdifferenz bei 100 Kelvin Temperatureunterschied
  calTemperatureSensorDiff = (calTemperatureSensor130Value - calTemperatureSensor30Value);
}

void CHIP_TEMPERATURE_Exec(uint32_t chiptemperature)
{
    int32_t voltage;
    //Aktuelle Spannung am Temp Sensor
    voltage = (3300 * chiptemperature) / 65536;


    voltage = voltage - calTemperatureSensor30Value;
    voltage = voltage * 100000; //100000 da Kalibrierwerte 100 Kelvin Delta T haben und wir alles in m°C rechnen
    voltage = voltage / (int32_t)(calTemperatureSensorDiff);
    voltage = voltage + 30000; //30000 da Erste Kalibrierpunkt bei 30°C --> 30 000 m°C

    //Durch 10 teilen, damit es in 16 Bit signed modbus register passt
    sys_data.s.values.chipTemperature = voltage /10 ;

	calc_temp_compensation();
}

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

void calc_temp_compensation(void)
{
  #define sv sys_data.s.values
  #define sp sys_data.s.parameter

  sv.uBatEmptyTempComp = sp.uBatEmpty;

  if (sv.chipTemperature < sp.uBatEmptyCompStartTemp)
  {
	  int16_t currentTemp = sv.chipTemperature;
	  if (sv.chipTemperature <= sp.uBatEmptyCompStopTemp) currentTemp = sp.uBatEmptyCompStopTemp;

	  sv.uBatEmptyTempComp = y(sp.uBatEmptyCompStopTemp,						// x1 -20°C
							   sp.uBatEmptyCompStopVolt,						// y1  2.5V * 4 = 10V oder 2.5V * 8 = 20V
							   sp.uBatEmptyCompStartTemp,						// x2  5°C
							   sp.uBatEmpty,									// y2  3.1V * 4 = 12.4V oder 3.1V * 8 = 24.8V
							   currentTemp);									// x   T°C
  }

  #undef sp
  #undef sv
}

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

/*!
 *  \brief    Linear Rescale function.
 *
 *            Converts all numbers from range [x1, x2] into range [y1, y2].
 *            x1 must not be equal to x2.
 *
 *  \param    x1: left limit of the input range.
 *  \param    x2: right limit of the input range.
 *  \param    y1: left limit of the output range.
 *  \param    y2: right limit of the output range.
 *  \param     x: number to convert from the input range.
 *  \return       converted result from the output range.
 */
int16_t y(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x)
{
    int32_t X1 = x1 <= x2 ? x1: x2;
    int32_t Y1 = y1 <= y2 ? y1: y2;
    int32_t X2 = x2 > x1 ? x2: x1;
    int32_t Y2 = y2 > y1 ? y2: y1;
    int32_t X = x;

    int32_t div = X2 - X1;
    if (!div) return 0;
    int32_t fraction = (Y2 - Y1) * (X - X1) + Y1 * (X2 - X1);
    int32_t res = fraction / div;

    return (int16_t)res;
}

/*************************** End of file ****************************/