//=================================================================================================
//
// Company:       Paul Scherrer Institut
//                5232 Villigen PSI
//                Switzerland
//
//-------------------------------------------------------------------------------------------------
//
// Project:       High Stability Current Source
// Author:        Lukas Kuenzi  (lukas.kuenzi@psi.ch)
//
//-------------------------------------------------------------------------------------------------
//
// Module:        Main Application
// Filename:      MAIN_MainApplication.c
// Date:          Handled by Subversion (version control system)
// Revision:      Handled by Subversion (version control system)
// History:       Handled by Subversion (version control system)
//
//-------------------------------------------------------------------------------------------------
//
// Description:   HVCT_HvController
//
//=================================================================================================



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

#include "../PDEF_ProjectDefinitions.h"
#include "MAIN_MainApplication.h"

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

// Drivers
#include "../Drivers/TEMP_Temperature.h"
#include "../Drivers/DIPO_DigitalPorts.h"
#include "../Drivers/CAND_CanDriver.h"
#include "../Drivers/PECO_PeltierController.h"
#include "../Drivers/ANPI_AnalogPortsIn.h"

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

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

#include "cmsis_os2.h" 

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

#define SLOW_TEXT                   (U32)0x83767987
#define FAST_TEXT                   (U32)0x46415354

#define MSG_QUEUE_SIZE							8


#define EVENT_NEW_MESSAGE 					((U32)(1<<0))
#define EVENT_TIMER_UPDATE					((U32)(1<<1))

#define EVENT_FLAGS_ALL             ( EVENT_NEW_MESSAGE | EVENT_TIMER_UPDATE )

//=================================================================================================
// 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 VOID vMainTask( PVOID arg );
PRIVATE VOID vEventCallback( PVOID pvData );
PRIVATE VOID vMsgRxCallback( CAND_Message stMessage );
//PRIVATE BOOL boSetValCheck( PVOID pvCallbackData, VARH_UVariable uNewValue );

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

LOCAL osThreadId_t        m_pstThreadID       		= NULL;
LOCAL osMessageQueueId_t  m_pstCANRxMsgQueueID    = NULL;
LOCAL osEventFlagsId_t    m_pstEventID        		= NULL;



LOCAL osTimerId_t         m_pstUpdateTimer    = NULL;


LOCAL U32                 m_u32DataCnt        = 0;

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

LOCAL CONST osThreadAttr_t stTaskAttribute =
{
  "MAIN_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)
};


LOCAL CONST osMessageQueueAttr_t stCANRxMsgQueueAttribute =
{
  "MAIN_CAN_Rx_Queue",             // name of the message queue
  0,                                // attribute bits
  NULL,                             // memory for control block
  0,                                // size of provided memory for control block
  NULL,                             // memory for data storage
  0,                                // size of provided memory for data storage 
};



LOCAL CONST osEventFlagsAttr_t stEventAttribute =
{ 
  "MAIN_Event_Flags",               // name of the event flags 
  0,                                // attribute bits 
  NULL,                             // memory for control block
  0,                                // size of provided memory for control block
};

LOCAL CONST osTimerAttr_t stTimerAttribute =
{ 
  "MAIN_UpdateTimer",               // name of the timer
  0,                                // attribute bits
  NULL,                             // memory for control block
  0,                                // size of provided memory for control block
};

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



//=================================================================================================
// Section:       EXTERNAL VARIABLES
// Description:   Definition of external (global) variables.
//=================================================================================================
//extern CRC_HandleTypeDef hcrc;

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


//-------------------------------------------------------------------------------------------------
// Function:      MAIN_boInitializeModule
// Description:   Initializes the module. Function must be called once immediately after power-up.
// Parameters:    None
// Returns:       Boolean TRUE if successful
//-------------------------------------------------------------------------------------------------

BOOL MAIN_boInitializeModule( VOID )  
{
  BOOL boOK = TRUE;
   
  boOK &= ((m_pstEventID = osEventFlagsNew( &stEventAttribute )) == NULL) ? FALSE : TRUE; 
  boOK &= ((m_pstThreadID = osThreadNew( vMainTask, NULL, &stTaskAttribute )) == NULL ) ? FALSE : TRUE;
	boOK &= ((m_pstCANRxMsgQueueID = osMessageQueueNew( MSG_QUEUE_SIZE, sizeof(CAND_Message), &stCANRxMsgQueueAttribute ) ) == NULL ) ? FALSE : TRUE;
  boOK &= (m_pstUpdateTimer = osTimerNew( vEventCallback, osTimerPeriodic, (PVOID)EVENT_TIMER_UPDATE, &stTimerAttribute )) == NULL  ? FALSE : TRUE;
  
	/*boOK &= VARH_boRegisterRangeCheck( VARH_eVoltageRefEn,	VARH_boBooleanVarCheck, NULL );
	
	boOK &= VARH_boRegisterRangeCheck( VARH_eStatusG,       VARH_boBooleanVarCheck, NULL );
	boOK &= VARH_boRegisterRangeCheck( VARH_eStatusR,       VARH_boBooleanVarCheck, NULL );
	boOK &= VARH_boRegisterRangeCheck( VARH_eEnabledG,      VARH_boBooleanVarCheck, NULL );
	boOK &= VARH_boRegisterRangeCheck( VARH_eEnabledR,      VARH_boBooleanVarCheck, NULL );
	boOK &= VARH_boRegisterRangeCheck( VARH_eInvertedG,     VARH_boBooleanVarCheck, NULL );
	boOK &= VARH_boRegisterRangeCheck( VARH_eInvertedR,     VARH_boBooleanVarCheck, NULL );
	boOK &= VARH_boRegisterRangeCheck( VARH_eSpareG,        VARH_boBooleanVarCheck, NULL );
	boOK &= VARH_boRegisterRangeCheck( VARH_eSpareR,        VARH_boBooleanVarCheck, NULL );
	
	boOK &= VARH_boRegisterNotification( VARH_eVoltageRefEn,     VARH_eNewValue, vEventCallback, (PVOID)EVENT_VREF ); 
	
	boOK &= VARH_boRegisterNotification( VARH_eStatusG,     VARH_eNewValue, vEventCallback, (PVOID)EVENT_STATUS_G ); 
	boOK &= VARH_boRegisterNotification( VARH_eStatusR,     VARH_eNewValue, vEventCallback, (PVOID)EVENT_STATUS_R ); 
	boOK &= VARH_boRegisterNotification( VARH_eEnabledG,    VARH_eNewValue, vEventCallback, (PVOID)EVENT_ENABLE_G ); 
	boOK &= VARH_boRegisterNotification( VARH_eEnabledR,    VARH_eNewValue, vEventCallback, (PVOID)EVENT_ENABLE_R ); 
	boOK &= VARH_boRegisterNotification( VARH_eInvertedG,   VARH_eNewValue, vEventCallback, (PVOID)EVENT_INVERT_G ); 
	boOK &= VARH_boRegisterNotification( VARH_eInvertedR,   VARH_eNewValue, vEventCallback, (PVOID)EVENT_INVERT_R ); 
	boOK &= VARH_boRegisterNotification( VARH_eSpareG,      VARH_eNewValue, vEventCallback, (PVOID)EVENT_SPARE_G ); 
	boOK &= VARH_boRegisterNotification( VARH_eSpareR,      VARH_eNewValue, vEventCallback, (PVOID)EVENT_SPARE_R ); 
	
  boOK &= VARH_boRegisterRangeCheck( VARH_eEnable,        VARH_boBooleanVarCheck, NULL );
  boOK &= VARH_boRegisterRangeCheck( VARH_eInvertA,       VARH_boBooleanVarCheck, NULL );
  boOK &= VARH_boRegisterRangeCheck( VARH_eInvertB,       VARH_boBooleanVarCheck, NULL );
  boOK &= VARH_boRegisterRangeCheck( VARH_eSetMode,       VARH_boBooleanVarCheck, NULL );
  boOK &= VARH_boRegisterRangeCheck( VARH_eDACStartStop,  VARH_boBooleanVarCheck, NULL );
  boOK &= VARH_boRegisterRangeCheck( VARH_eExtSyncEnable, VARH_boBooleanVarCheck, NULL );
  boOK &= VARH_boRegisterRangeCheck( VARH_eSetValue,      boSetValCheck, NULL );  

  boOK &= VARH_boRegisterNotification( VARH_eEnable,        VARH_eRising,   vEventCallback, (PVOID)EVENT_ENABLE );
  boOK &= VARH_boRegisterNotification( VARH_eEnable,        VARH_eFalling,  vEventCallback, (PVOID)EVENT_DISABLE );  
  boOK &= VARH_boRegisterNotification( VARH_eInvertA,       VARH_eNewValue, vEventCallback, (PVOID)EVENT_INVERT );  
  boOK &= VARH_boRegisterNotification( VARH_eInvertB,       VARH_eNewValue, vEventCallback, (PVOID)EVENT_INVERT );  
  boOK &= VARH_boRegisterNotification( VARH_eExtSyncEnable, VARH_eNewValue, vEventCallback, (PVOID)EVENT_EXT_SYNC_ENABLE );  
  boOK &= VARH_boRegisterNotification( VARH_eSetValue,      VARH_eNewValue, vEventCallback, (PVOID)EVENT_NEW_SET_VALUE ); 
  boOK &= VARH_boRegisterNotification( VARH_eSetMode,       VARH_eNewValue, vEventCallback, (PVOID)EVENT_NEW_MODE ); 
  boOK &= VARH_boRegisterNotification( VARH_eDACStartStop,  VARH_eRising,   vEventCallback, (PVOID)EVENT_DAC_START ); 
  boOK &= VARH_boRegisterNotification( VARH_eDACStartStop,  VARH_eFalling,  vEventCallback, (PVOID)EVENT_DAC_STOP ); */

  // config DAC and ADC
  // DACD_boConfig( BOOL boFast, CALI_St* pstOffsetGain, DACD_pfnWaveformCallback pfnWaveform, U16 u16WaveformLength )
  // ADCD_boConfig( BOOL boFast, CALI_St* pstGainOffset, vEventCallback, (PVOID)EVENT_ADC_DATA_READY  )

  boOK &= (osTimerStart( m_pstUpdateTimer, 1000 ) == osOK ) ? TRUE : FALSE;
	
	CAND_vSetRxCallback(vMsgRxCallback);
  
  return( boOK );
}

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

//-------------------------------------------------------------------------------------------------
// Function:      vMainTask
// Description:   Main Application Task
// Parameters:    None
// Returns:       None
//-------------------------------------------------------------------------------------------------
PRIVATE VOID vMainTask( PVOID arg )
{
  UNUSED( arg );
  U32 u32Flags;

  U8 au8Buffer[8];
	
  while( TRUE )
  {
		
		u32Flags = osEventFlagsWait( m_pstEventID, EVENT_FLAGS_ALL, osFlagsWaitAny, osWaitForever );
		
		if( u32Flags & EVENT_NEW_MESSAGE ) {

			CAND_Message stMessage;
      osMessageQueueGet( m_pstCANRxMsgQueueID, &stMessage, NULL, 0 );
			
			if(stMessage.u8Id == 0x10){

				S16 ControlVoltage = ((S16)(ANPI_flGetInputValue(ANPI_eControlVoltage)*1000));
				
				au8Buffer[0] = (ControlVoltage & 0xFF00) >> 8;
				au8Buffer[1] = ControlVoltage & 0xFF;
				
				CAND_boSendMessage(0x11, 2, au8Buffer);

			} else if(stMessage.u8Id == 0x12){

				S16 s16Voltage = stMessage.au8Data[0] << 8;
				s16Voltage |= stMessage.au8Data[1];
				PECO_boSetTemperature( s16Voltage );
				
			} else if(stMessage.u8Id == 0x13){

				S16 SupplyVoltage24V = ((S16)(ANPI_flGetInputValue(ANPI_eSupplyVoltage24V)*1000));
				S16 SupplyCurrent24V = ((S16)(ANPI_flGetInputValue(ANPI_eSupplyCurrent24V)*1000));
				S16 OutputVoltage = ((S16)(ANPI_flGetInputValue(ANPI_eOutputVoltage)*1000));
				S16 OutputCurrent = ((S16)(ANPI_flGetInputValue(ANPI_eOutputCurrent)*1000));

				/*U16 SupplyVoltage24V = ANPI_flGetInputValue(ANPI_eSupplyVoltage24V);
        U16 SupplyCurrent24V = ANPI_flGetInputValue(ANPI_eSupplyCurrent24V);
        U16 OutputVoltage = ANPI_flGetInputValue(ANPI_eOutputVoltage);
        U16 OutputCurrent = ANPI_flGetInputValue(ANPI_eOutputCurrent);*/
				
				au8Buffer[0] = (SupplyVoltage24V & 0xFF00) >> 8;
				au8Buffer[1] = SupplyVoltage24V & 0xFF;
				au8Buffer[2] = (SupplyCurrent24V & 0xFF00) >> 8;
				au8Buffer[3] = SupplyCurrent24V & 0xFF;
				au8Buffer[4] = (OutputVoltage & 0xFF00) >> 8;
				au8Buffer[5] = OutputVoltage & 0xff;
				au8Buffer[6] = (OutputCurrent & 0xFF00) >> 8;
				au8Buffer[7] = OutputCurrent & 0xFF;
				
				CAND_boSendMessage(0x14, 8, au8Buffer);
				
			} else if(stMessage.u8Id == 0x15){

			  S16 Cold = (S16)(TEMP_dGetValue(ADCD_eCold)*100);
				S16 Hot = (S16)(TEMP_dGetValue(ADCD_eHot)*100);
				
				au8Buffer[0] = (Cold & 0xFF00) >> 8;
				au8Buffer[1] = (Cold & 0xFF);
				au8Buffer[2] = (Hot & 0xFF00) >> 8;
				au8Buffer[3] = (Hot & 0xFF);
				
				CAND_boSendMessage(0x16, 4, au8Buffer);

			} else if(stMessage.u8Id == 0x17){

				PECO_Enable(TRUE);

			} else if(stMessage.u8Id == 0x18){

				PECO_Enable(FALSE);

			}
			
			
    }
		if( u32Flags & EVENT_TIMER_UPDATE )
    {
			DIPO_vToggleOutput(DIPO_eLED);
		}
        
  }
}

//-------------------------------------------------------------------------------------------------
// Function:      vEventCallback
// Description:   Callback for events
// Parameters:    None
// Returns:       None
//-------------------------------------------------------------------------------------------------
PRIVATE VOID vEventCallback( PVOID pvData )
{
  osEventFlagsSet( m_pstEventID, (U32)pvData );
}

//-------------------------------------------------------------------------------------------------
// Function:      vEventCallback
// Description:   Callback for events
// Parameters:    None
// Returns:       None
//-------------------------------------------------------------------------------------------------
PRIVATE VOID vMsgRxCallback( CAND_Message stMessage )
{
  osMessageQueuePut(m_pstCANRxMsgQueueID, &stMessage, 0, 0);
	osEventFlagsSet( m_pstEventID, EVENT_NEW_MESSAGE );
}


//-------------------------------------------------------------------------------------------------
// Function:      boSetValCheck
// Description:   Checks the range of the set value
// Parameters:    PVOID pvCallbackData
//                VARH_UVariable uNewValue
// Returns:       TRUE, the variable can be written
//-------------------------------------------------------------------------------------------------
/*PRIVATE BOOL boSetValCheck( PVOID pvCallbackData, VARH_UVariable uNewValue )
{
  UNUSED( pvCallbackData );
  return( uNewValue.flVal <= 200.0f && uNewValue.flVal >= -200.0f ? FALSE : TRUE );
}
*/

