//=================================================================================================
//
// Company:       Paul Scherrer Institut
//                5232 Villigen PSI
//                Switzerland
//
//-------------------------------------------------------------------------------------------------
//
// Project:       Peltier Controller V2
// Author:        Noah Piqué (noah.pique@psi.ch)
//
//-------------------------------------------------------------------------------------------------
//
// Module:        Temp
// Filename:      TEMP_Temperature.c
// Date:          Handled by Subversion (version control system)
// Revision:      Handled by Subversion (version control system)
// History:       Handled by Subversion (version control system)
//
//-------------------------------------------------------------------------------------------------
//
// Description:   This source file contains all functions dealing with the temperature readout
//
//=================================================================================================



//=================================================================================================
// Section:       INCLUDES
// Description:   List of required include files.
//=================================================================================================

//#include "../Application/VARH_VariableHandler.h"
#include "../PDEF_ProjectDefinitions.h"
#include "TEMP_Temperature.h"

// Application
//#include "../Application/ELOG_ErrorLogger.h"
//#include "../Application/RTOS_RealTimeOs.h"

// Toolbox
//#include "../Toolbox/ASRT_Assert.h"
#include "../Toolbox/UTIL_Utility.h"

// Drivers

#include "DIPO_DigitalPorts.h"
#include "SPID_SpiDriver.h"
#include "ADCD_ADCDriver.h"

// include STM32 drivers
#include "stm32l4xx_hal.h"

#include <math.h>

#include "cmsis_os2.h" 

//=================================================================================================
// Section:       DEFINITIONS
// Description:   Definition of local constants (visible by this module only).
//=================================================================================================

#define REFRESH_MS 100

// Konstanten f�r Temperaturberechung
#define RTD_A 3.9083e-3 
#define RTD_B -5.775e-7

#define R_REF 4000
#define R_NOMINAL 1000

//=================================================================================================
// Section:       MACROS
// Description:   Definition of local macros (visible by this module only).
//=================================================================================================



//=================================================================================================
// Section:       ENUMERATIONS
// Description:   Definition of local enumerations (visible by this module only).
//=================================================================================================


//=================================================================================================
// Section:       STRUCTURES
// Description:   Definition of local Structures (visible by this module only).
//=================================================================================================

//=================================================================================================
// Section:       LOCAL FUNCTIONS (PROTOTYPES)
// Description:   Definition of local functions (visible by this module only).
//=================================================================================================

PRIVATE FLOAT flConvertADCData( U16 dbRTemp );
PRIVATE VOID vTempTask( PVOID arg );

//=================================================================================================
// Section:       LOCAL CONSTANTS
// Description:   Definition of local constants (visible by this module only).
//=================================================================================================

LOCAL CONST osMutexAttr_t m_stMutexAttr =
{
  "TEMP_Mutex",                             // human readable mutex name
  osMutexRecursive | osMutexPrioInherit,    // attr_bits
  NULL,                                     // memory for control block   
  0U                                        // size for control block
};

LOCAL CONST osThreadAttr_t stTaskAttribute =
{
  "TEMP_Thread",                    // name of the thread
  osThreadDetached,                 // attribute bits
  NULL,                             // memory for control block
  0,                                // size of provided memory for control block
  NULL,                             // memory for stack
  1024,                             // size of stack
  osPriorityNormal,                 // initial thread priority (default: osPriorityNormal)
  0,                                // TrustZone module identifier
  0,                                // reserved (must be 0)
};

//=================================================================================================
// Section:       LOCAL VARIABLES
// Description:   Definition of local variables (visible by this module only).
//=================================================================================================

LOCAL osThreadId_t      m_pstThreadID   	= NULL;
LOCAL osMutexId_t       m_pstMutexID    	= NULL;

LOCAL FLOAT m_flTempData[ADCD_eNumberOfTemps];

//=================================================================================================
// Section:       EXTERNAL FUNCTIONS
// Description:   Definition of external (global) functions.
//=================================================================================================



//=================================================================================================
// Section:       EXTERNAL VARIABLES
// Description:   Definition of external (global) variables.
//=================================================================================================



//=================================================================================================
// Section:       GLOBAL FUNCTIONS
// Description:   Definition (implementation) of global functions.
//=================================================================================================

//-------------------------------------------------------------------------------------------------
// Function:      TEMP_boInitializeModule
// Description:   Initializes the module. Function must be called once immediately after power-up.
//                This function is thread save
// Parameters:    None
// Returns:       Boolean TRUE if successful
//-------------------------------------------------------------------------------------------------
BOOL TEMP_boInitializeModule( VOID )
{ 
  BOOL boOK = TRUE;

  boOK &= ((m_pstThreadID = osThreadNew( vTempTask, NULL, &stTaskAttribute )) == NULL ) ? FALSE : TRUE;
  boOK &= ((m_pstMutexID = osMutexNew( &m_stMutexAttr )) == NULL) ? FALSE : TRUE;

  return( boOK );
}

//-------------------------------------------------------------------------------------------------
// Function:      TEMP_dGetValue
// Description:   Gets the desired temperature
// Parameters:    ATEMP_EnTemperature enInput
// Returns:       DOUBLE DValue                 Value from ADC
//-------------------------------------------------------------------------------------------------
FLOAT TEMP_dGetValue( ADCD_EnTemps enTemp )
{

  osMutexAcquire( m_pstMutexID, osWaitForever );
  DOUBLE dValue = m_flTempData[enTemp];
  osMutexRelease( m_pstMutexID );
  
  return( dValue );
}

//-------------------------------------------------------------------------------------------------
// Function:      TEMP_boRegisterEventNotification
// Description:   Register for a notification when there are new values
// Parameters:    TEMP_pfnEventCallback pfnCallback
//                PVOID pvCallbackArgument
// Returns:       TRUE, if successfull, otherwise FALSE
//-------------------------------------------------------------------------------------------------
//BOOL TEMP_boRegisterEventNotification( TEMP_pfnEventCallback pfnCallback, PVOID pvCallbackArgument )
//{
//  BOOL boRet = FALSE;
//  osMutexAcquire( m_pstMutexID, osWaitForever );
//  for( U16 u16Cnt = 0; u16Cnt < NUMBER_OF_EVENT_CALLBACKS; u16Cnt++ )
//  {
//    if( m_apfnEventCallback[u16Cnt] == NULL )
//    {
//      m_apfnEventCallback[u16Cnt]   = pfnCallback;
//      m_apvCallbackArgument[u16Cnt] = pvCallbackArgument;
//      boRet = TRUE;
//      break;
//    }
//  }
//  osMutexRelease( m_pstMutexID );
//  return( boRet );
//}

//=================================================================================================
// Section:       LOCAL FUNCTIONS
// Descriptionn:  Definition (implementation) of local functions.
//=================================================================================================

//-------------------------------------------------------------------------------------------------
// Function:      vTempTask
// Description:   vTempTask
// Parameters:    None
// Returns:       None
//-------------------------------------------------------------------------------------------------
PRIVATE VOID vTempTask( PVOID arg )
{
  UNUSED( arg );
  U32 u32Flags;
	
	BOOL boOK = TRUE;
	U8 error;
	U16 u16ADC_data[ADCD_eNumberOfTemps];
	U8 u8Channel;
	
	FLOAT temp = 0;
	
	osDelay(10);
  
  while( TRUE )
  {		
		
		
		//u32Flags = osEventFlagsWait( m_pstEventID, EVENT_REFRESH, osFlagsWaitAny, osWaitForever );

    //if( u32Flags & EVENT_REFRESH  )
    //{	
      boOK &= ADCD_dReadData(ADCD_eHot, &error, &u16ADC_data[ADCD_eHot]);
			if( boOK )
			{
				osMutexAcquire( m_pstMutexID, osWaitForever );
				m_flTempData[ADCD_eHot] = flConvertADCData( u16ADC_data[ADCD_eHot] );
				//temp = flConvertADCData( u16ADC_data[ADCD_eHot] ); // for debugging
				//VARH_vSetVariableData( VARH_eTempHeatSink + u8Channel, (VARH_UVariable)(FLOAT)m_dbTempData[u8Channel] );
				osMutexRelease( m_pstMutexID );
			} else {
				boOK = TRUE;
			}
			boOK &= ADCD_dReadData(ADCD_eCold, &error, &u16ADC_data[ADCD_eCold]);
			if( boOK )
			{
				osMutexAcquire( m_pstMutexID, osWaitForever );
				m_flTempData[ADCD_eCold] = flConvertADCData( u16ADC_data[ADCD_eCold] );
				//temp = flConvertADCData( u16ADC_data[ADCD_eCold] ); // for debugging
				//VARH_vSetVariableData( VARH_eTempHeatSink + u8Channel, (VARH_UVariable)(FLOAT)m_dbTempData[u8Channel] );
				osMutexRelease( m_pstMutexID );
			} else {
				boOK = TRUE;
			}
    //}


		
		osDelay(REFRESH_MS);
		
		
		
		
    // wait for ADC conversions completed
//    u32Flags  = osEventFlagsWait( m_pstEventID, OS_EVENT_ADC_COMPLETED_FLAG, osFlagsWaitAll , ADC_TIMEOUT_MS );
//    boTimeout = (u32Flags == osFlagsErrorTimeout) ? TRUE : FALSE;
//    boError   = FALSE;
//    
//    // check if we have a timeout
//    if( boTimeout )
//    {
//      //ELOG_ADD_LOG( ELOG_eADCTimeout );
//    }
//    
//    // read ADC data
//    if( !(boSuccess = boReadADCData() ) )
//    {
//      //ELOG_ADD_LOG( ELOG_eADCReadingDataFailed ); 
//    }    
////    vIncrementChannel();
//    
//    // reinit ADC on error, on spi failure or when timeout reached
//    if( boTimeout || !boSuccess )
//    {
//      boError = TRUE;
////      vADCInit();
//    }
    
//    // send event to worker task, if all channels completed and no error
//    if( m_stADCData.u8Cannel == 0 && !boError )
//    {
//      // send event to tasks
//      for( U16 u16Cnt = 0; u16Cnt < NUMBER_OF_EVENT_CALLBACKS; u16Cnt++ )
//      {
//        if( m_apfnEventCallback[u16Cnt] != NULL )
//        {
//          m_apfnEventCallback[u16Cnt]( m_apvCallbackArgument[u16Cnt] );
//        }
//      }
//    }

  }
}

//-------------------------------------------------------------------------------------------------
// Function:      flConvertADCData
// Description:   Converts resistor value to temperature data
// Parameters:    U16 u16RTemp
// Returns:       U16, temperature in Celcius
//-------------------------------------------------------------------------------------------------
PRIVATE FLOAT flConvertADCData( U16 u16RTemp )
{

  FLOAT u16R = u16RTemp / 8192.0f;

  FLOAT flT = 9.9714f * u16R;
  flT += 235.904f;
  flT *= u16R;
  flT += -245.876f;

  /*DOUBLE flZ1, flZ2, flZ3, flZ4, flRt, flTemp, flRpoly;
        flRt = u16RTemp;
        flRt /= 32768;
        flRt *= R_REF;
        flZ1 = -RTD_A;
        flZ2 = RTD_A * RTD_A - (4 * RTD_B);
        flZ3 = (4 * RTD_B) / R_NOMINAL;
        flZ4 = 2 * RTD_B;
        flTemp = flZ2 + (flZ3 * flRt);
        flTemp = (sqrt(flTemp) + flZ1) / flZ4;
        if (flTemp >= 0)
          return flTemp;
        // ugh.
        flRt /= R_NOMINAL;
        flRt *= 100; // normalize to 100 ohm
        flRpoly = flRt;
        flTemp = -242.02;
        flTemp += 2.2228 * flRpoly;
        flRpoly *= flRt; // square
        flTemp += 2.5859e-3 * flRpoly;
        flRpoly *= flRt; // ^3
        flTemp -= 4.8260e-6 * flRpoly;
        flRpoly *= flRt; // ^4
        flTemp -= 2.8183e-8 * flRpoly;
        flRpoly *= flRt; // ^5
        flTemp += 1.5243e-10 * flRpoly;*/

  

  return( flT );
}
