//=================================================================================================
//
// Company:       Paul Scherrer Institut
//                5232 Villigen PSI
//                Switzerland
//
//-------------------------------------------------------------------------------------------------
//
// Project:       Peltier Controller V2
// Author:        Noah Piqu� (noah.pique@psi.ch)
//
//-------------------------------------------------------------------------------------------------
//
// Module:        Digital Ports
// Filename:      DIPO_DigitalPorts.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 digtial I/O ports
//                Convention: TRUE means active, FALSE means not active
//                The polarity of the signal is set in the initialization struct (boLowActive)
//                The name of the enumeration does not have any impact on the polarity
//                Even with a signal nCs, TRUE means active (if low active => output low)
//
//=================================================================================================



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

#include "../PDEF_ProjectDefinitions.h"
#include "DIPO_DigitalPorts.h"

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

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

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

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



//=================================================================================================
// 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).
//=================================================================================================
 
typedef struct
{
  GPIO_TypeDef*     pstPort;      // Port
  GPIO_InitTypeDef  stGPIOInit;	  // init structure
  BOOL              boResetState; // reset state of pin
  BOOL              boSetState;   // set state of pin
} StDigitalIO;                    // Represents one digital input or output



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



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

// Input order must fit enumeration "DIPO_EnDigitalInput".
LOCAL CONST StDigitalIO m_astInputs[DIPO_eInNumberOfInputs] =
{
	
	{ GPIOB, { GPIO_PIN_7,  GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, FALSE, TRUE },   // 00 DIPO_ePG
  { GPIOC, { GPIO_PIN_15,  GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, FALSE, TRUE },   // 01 DIPO_eADR3
	{ GPIOB, { GPIO_PIN_4,  GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, FALSE, TRUE },   // 01 DIPO_eADR2
	{ GPIOB, { GPIO_PIN_3,  GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, FALSE, TRUE },   // 02 DIPO_eADR1
	{ GPIOA, { GPIO_PIN_15,  GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, FALSE, TRUE },  // 03 DIPO_eADR0
	
};

// order must fit enumeration "DIPO_EnDigitalOutput".
LOCAL CONST StDigitalIO m_astOutputs[DIPO_eOutNumberOfOutputs] =
{  
	
	{ GPIOB, { GPIO_PIN_6, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, TRUE, FALSE },  // 00 DIPO_eCS_C
	{ GPIOB, { GPIO_PIN_5, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, TRUE, FALSE },  // 01 DIPO_eCS_H
	{ GPIOC, { GPIO_PIN_14, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, FALSE, TRUE }, // 02 DIPO_eLED
	{ GPIOA, { GPIO_PIN_8, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_MEDIUM, 0 }, FALSE, TRUE },  // 03 DIPO_eEN
	
};


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


//=================================================================================================
// 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:      DIPO_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 DIPO_boInitializeModule( VOID )
{
  U8 u8Cnt;
  BOOL boOK = TRUE;
  
    // enable APB2 syscfg clock
   __HAL_RCC_SYSCFG_CLK_ENABLE();
  
  // initialize the inputs
  // ----------------------
  if( DIPO_eInNumberOfInputs > 0 )
  {
    for( u8Cnt = 0 ; u8Cnt < DIPO_eInNumberOfInputs; u8Cnt++ )
    {
      boOK &= (m_astInputs[u8Cnt].stGPIOInit.Mode == GPIO_MODE_INPUT) ? TRUE : FALSE;

      // configure the GIO pin
      HAL_GPIO_Init( m_astInputs[u8Cnt].pstPort, (GPIO_InitTypeDef*)&m_astInputs[u8Cnt].stGPIOInit );
    }
  }

  // initialize the outputs
  // ----------------------  
  if( DIPO_eOutNumberOfOutputs > 0 )
  {
    for( u8Cnt = 0 ; u8Cnt < DIPO_eOutNumberOfOutputs; u8Cnt++ )
    {
      boOK &= (m_astOutputs[u8Cnt].stGPIOInit.Mode == GPIO_MODE_OUTPUT_PP ||  m_astOutputs[u8Cnt].stGPIOInit.Mode == GPIO_MODE_OUTPUT_OD) ? TRUE : FALSE;
      
      // disable output
      DIPO_vResetOutput( (DIPO_EnDigitalOutput)u8Cnt );

      HAL_GPIO_Init( m_astOutputs[u8Cnt].pstPort, (GPIO_InitTypeDef*)&m_astOutputs[u8Cnt].stGPIOInit );
    }
  }
  
  return( boOK );
}


//-------------------------------------------------------------------------------------------------
// Function:      DIPO_vSetOutput
// Description:   Turns a digital output on or off.
// Parameters:    DIPO_EnDigitalOutput enOutput   Digital output to set on or off
// Returns:       None
//-------------------------------------------------------------------------------------------------
VOID DIPO_vSetOutput( DIPO_EnDigitalOutput enOutput )
{
  #if defined(PDEF_FUNCTION_PARAMETER_CHECK_ENABLED) && PDEF_FUNCTION_PARAMETER_CHECK_ENABLED == TRUE
  if( enOutput >= DIPO_eOutNumberOfOutputs )
  {
    ELOG_ADD_LOG( ELOG_eInvalidFunctionParameter );
    return;
  }
  #endif
  
  HAL_GPIO_WritePin( m_astOutputs[enOutput].pstPort, (U16)m_astOutputs[enOutput].stGPIOInit.Pin, (GPIO_PinState) m_astOutputs[enOutput].boSetState );
}


//-------------------------------------------------------------------------------------------------
// Function:      DIPO_vResetOutput
// Description:   Sets the output in reset state
// Parameters:    DIPO_EnDigitalOutput enOutput   Digital output
// Returns:       None
//-------------------------------------------------------------------------------------------------
VOID DIPO_vResetOutput( DIPO_EnDigitalOutput enOutput )
{
  #if defined(PDEF_FUNCTION_PARAMETER_CHECK_ENABLED) && PDEF_FUNCTION_PARAMETER_CHECK_ENABLED == TRUE
  if( enOutput >= DIPO_eOutNumberOfOutputs )
  {
    ELOG_ADD_LOG( ELOG_eInvalidFunctionParameter );
    return;
  }
  #endif
  
  HAL_GPIO_WritePin( m_astOutputs[enOutput].pstPort, (U16)m_astOutputs[enOutput].stGPIOInit.Pin, (GPIO_PinState) m_astOutputs[enOutput].boResetState );
}

//-------------------------------------------------------------------------------------------------
// Function:      DIPO_vSetState
// Description:   Sets the output state
// Parameters:    DIPO_EnDigitalOutput enOutput   Digital output
//                BOOL boState
// Returns:       None
//-------------------------------------------------------------------------------------------------
VOID DIPO_vSetState( DIPO_EnDigitalOutput enOutput, BOOL boState )
{
  #if defined(PDEF_FUNCTION_PARAMETER_CHECK_ENABLED) && PDEF_FUNCTION_PARAMETER_CHECK_ENABLED == TRUE
  if( enOutput >= DIPO_eOutNumberOfOutputs )
  {
    ELOG_ADD_LOG( ELOG_eInvalidFunctionParameter );
    return;
  }
  #endif
  
  if( boState )
  {
    HAL_GPIO_WritePin( m_astOutputs[enOutput].pstPort, (U16)m_astOutputs[enOutput].stGPIOInit.Pin, (GPIO_PinState) m_astOutputs[enOutput].boSetState );
  }
  else
  {
    HAL_GPIO_WritePin( m_astOutputs[enOutput].pstPort, (U16)m_astOutputs[enOutput].stGPIOInit.Pin, (GPIO_PinState) m_astOutputs[enOutput].boResetState );
  }
}

//-------------------------------------------------------------------------------------------------
// Function:      DIPO_vGetOutput
// Description:   Reads back a digital output.
// Parameters:    DIPO_EnDigitalOutput enOutput     Digital output to get the data value                   
// Returns:       BOOL                              TRUE, if output is active, otherwise FALSE
//-------------------------------------------------------------------------------------------------
BOOL DIPO_boGetOutput( DIPO_EnDigitalOutput enOutput )
{
  #if defined(PDEF_FUNCTION_PARAMETER_CHECK_ENABLED) && PDEF_FUNCTION_PARAMETER_CHECK_ENABLED == TRUE
  if( enOutput >= DIPO_eOutNumberOfOutputs || !IS_GPIO_ALL_INSTANCE( m_astOutputs[enOutput].pstPort ) || !IS_GPIO_PIN( m_astOutputs[enOutput].stGPIOInit.Pin ) )
  {
    ELOG_ADD_LOG( ELOG_eInvalidFunctionParameter );
    return( FALSE );
  }
  #endif
  
  BOOL boBitState = TRUE;
  
  if( READ_BIT( m_astOutputs[enOutput].pstPort->ODR, m_astOutputs[enOutput].stGPIOInit.Pin ) == 0 )
  {
    boBitState = FALSE;
  }

  return( ( m_astOutputs[enOutput].boSetState == TRUE &&  boBitState == TRUE ) ||\
          ( m_astOutputs[enOutput].boResetState == TRUE &&  boBitState == FALSE ) ? TRUE : FALSE ); 
}

//-------------------------------------------------------------------------------------------------
// Function:      DIPO_boGetInput
// Description:   Reads a digital input 
// Parameters:    DIPO_EnDigitalInput enInput       Digital input to read                  
// Returns:       BOOL                              TRUE, if intput is set active, otherwise FALSE
//-------------------------------------------------------------------------------------------------
BOOL DIPO_boGetInput( DIPO_EnDigitalInput enInput )
{
  #if defined(PDEF_FUNCTION_PARAMETER_CHECK_ENABLED) && PDEF_FUNCTION_PARAMETER_CHECK_ENABLED == TRUE
  if( enInput >= DIPO_eInNumberOfInputs )
  {
    ELOG_ADD_LOG( ELOG_eInvalidFunctionParameter );
    return( FALSE );
  }
  #endif
    
  GPIO_PinState enPinState = HAL_GPIO_ReadPin( m_astInputs[enInput].pstPort, (U16)m_astInputs[enInput].stGPIOInit.Pin );
  
  return( ( m_astInputs[enInput].boSetState == TRUE && enPinState == GPIO_PIN_SET) ||\
          ( m_astInputs[enInput].boResetState == TRUE &&  enPinState == GPIO_PIN_RESET) ? TRUE : FALSE ); 
}


//-------------------------------------------------------------------------------------------------
// Function:      DIPO_vToggleOutput
// Description:   Toggles the digital output 
// Parameters:    DIPO_EnDigitalOutput enOutput Digital output to toggle                  
// Returns:       None
//-------------------------------------------------------------------------------------------------
VOID DIPO_vToggleOutput( DIPO_EnDigitalOutput enOutput )
{
  #if defined(PDEF_FUNCTION_PARAMETER_CHECK_ENABLED) && PDEF_FUNCTION_PARAMETER_CHECK_ENABLED == TRUE
  if( enOutput >= DIPO_eOutNumberOfOutputs )
  {
    ELOG_ADD_LOG( ELOG_eInvalidFunctionParameter );
    return;
  }
  #endif
  
  HAL_GPIO_TogglePin( m_astOutputs[enOutput].pstPort, (U16)m_astOutputs[enOutput].stGPIOInit.Pin );
}

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