//=================================================================================================
//
// Company:       Paul Scherrer Institut
//                5232 Villigen PSI
//                Switzerland
//
//-------------------------------------------------------------------------------------------------
//
// Project:       Peltier Controller V3
// Author:        Noah Piqué (noah.pique@psi.ch)
//
//-------------------------------------------------------------------------------------------------
//
// Module:        Utility
// Filename:      UTIL_Utility.h
// Date:          Handled by Subversion (version control system)
// Revision:      Handled by Subversion (version control system)
// History:       Handled by Subversion (version control system)
//
//-------------------------------------------------------------------------------------------------


#ifndef UTIL_UTILITY_H
#define UTIL_UTILITY_H

#ifdef __cplusplus
extern "C" {
#endif



//=================================================================================================
// Section:       INCLUDES
// Description:   List of required include files (visible by all modules).
//=================================================================================================

#include "string.h"
#include "stdio.h"
#include "../SDEF_StandardDefinitions.h"
  
// include STM32 drivers
#include "stm32l4xx_hal.h"
  
//=================================================================================================
// Section:       DEFINITIONS
// Description:   Definition of global constants (visible by all modules).
//=================================================================================================



//=================================================================================================
// Section:       MACROS
// Description:   Definition of global macros (visible by all modules).
//=================================================================================================

//macro for filename without path
/* #define _FILE_  ((PSZ)(strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : \
                (strrchr(__FILE__, '\\') ? (strrchr(__FILE__, '\\') + 1) : __FILE__)))*/
                
#define _FILE_ __FILE__

#define _LINE_  __LINE__

//checks if a pointer is valid
#define UTIL_IS_FUNC( pfnFoo )   ( pfnFoo != NULL )

#define UTIL_32BitAlign( u32Address ) ((((U32)((u32Address)+4UL)/4UL))*4UL)

#define UTIL_IS_POWER_OF_TWO( u32Numb )    ((u32Numb & (u32Numb - 1)) == 0)

#define UTIL_u16ConcatenateBytes( u8UpperByte, u8LowerByte)   ( (U16)((U16)u8UpperByte << 8) | (U16)u8LowerByte )

// approx delay of 1us
#define DELAY_US( u32Us ) do{\
                          for( U32 u32Cnt = (SystemCoreClock >> 24U) * (u32Us); u32Cnt > 0U; u32Cnt-- ) \
                          { \
                            __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
                            __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); \
                          }\
                          }while(0)

#define DELAY_MS( u32Ms ) do{\
                          for( U32 u32Cnt = (SystemCoreClock >> 14U) * (u32Ms); u32Cnt > 0U; u32Cnt-- ) \
                          { \
                             __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();\
                             __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();\
                          }\
                          }while(0)
                          

#ifndef UNUSED
  #define UNUSED(x) ((void)(x))
#endif  

#define UTIL_SET_BIT( u32Add, u32BitMask )     ( *(VOLATILE PU32)u32Add |= (u32BitMask) ) 
#define UTIL_CLEAR_BIT( u32Add, u32BitMask )   ( *(VOLATILE PU32)u32Add &= ~(u32BitMask) ) 

 #define UTIL_DEFINE_CRITICAL()  U32 u32PRIMASK 
 
// Enter Critical:
// implements a memory barrier to ensure memory operations completed before
// stores the interrupt status register
// disables interrupts
#define UTIL_ENTER_CRITICAL()         do{ \
                                            __DMB(); \
                                            u32PRIMASK = __get_PRIMASK(); \
                                            __disable_irq(); \
                                          }while(0)                                      
   
// Exit Critical:
// implements a memory barrier to ensure memory operations completed before
// restores the interrupt status register
#define UTIL_EXIT_CRITICAL()          do{                                   \
                                            __DMB();                        \
                                            __set_PRIMASK( u32PRIMASK );    \
                                        }while(0)
                                        
// bit band definitions                                      
#define UTIL_BB_SRAM( Address, BitNumber )     (*(VOLATILE PU32)(SRAM_BB_BASE     +   ((U32)Address - SRAM_BASE)*32       + BitNumber*4 ) )
#define UTIL_BB_BKRAM( Address, BitNumber )    (*(VOLATILE PU32)(BKPSRAM_BB_BASE  +   ((U32)Address - BKPSRAM_BASE)*32    + BitNumber*4 ) )
#define UTIL_BB_PERI( Address, BitNumber )     (*(VOLATILE PU32)(PERIPH_BB_BASE   +   ((U32)Address - PERIPH_BASE)*32     + BitNumber*4 ) )
                                   
// Basic bit band function definitions
#define UTIL_BB_SRAM_ClearBit( Address, BitNumber)   (UTIL_BB_SRAM( Address, BitNumber ) = 0)
#define UTIL_BB_SRAM_SetBit( Address, BitNumber)     (UTIL_BB_SRAM( Address, BitNumber ) = 1)
#define UTIL_BB_SRAM_GetBit( Address, BitNumber)     UTIL_BB_SRAM( Address, BitNumber )
 
#define UTIL_BB_PERI_ClearBit( Address, BitNumber)   (UTIL_BB_PERI( Address, BitNumber ) = 0)
#define UTIL_BB_PERI_SetBit( Address, BitNumber)     (UTIL_BB_PERI( Address, BitNumber ) = 1)
#define UTIL_BB_PERI_GetBit( Address, BitNumber)     UTIL_BB_PERI( Address, BitNumber )

#define UTIL_BB_BKRAM_ClearBit( Address, BitNumber)  (UTIL_BB_BKRAM( Address, BitNumber ) = 0)
#define UTIL_BB_BKRAM_SetBit( Address, BitNumber)    (UTIL_BB_BKRAM( Address, BitNumber ) = 1)
#define UTIL_BB_BKRMA_GetBit( Address, BitNumber)    UTIL_BB_BKRAM( Address, BitNumber )

// Checks, if the core is in debug mode
#define UTIL_IS_DEBUGGER_ATTACHED()     (CoreDebug_DHCSR_C_DEBUGEN_Msk & CoreDebug->DHCSR)

//=================================================================================================
// Section:       ENUMERATIONS
// Description:   Definition of global enumerations (visible by all modules).
//=================================================================================================



//=================================================================================================
// Section:       STRUCTURES
// Description:   Definition of global Structures (visible by all modules).
//=================================================================================================



//=================================================================================================
// Section:       GLOBAL VARIABLES
// Description:   Definition of global variables (visible by all modules).
//=================================================================================================



//=================================================================================================
// Section:       GLOBAL CONSTANTS
// Description:   Definition of global constants (visible by all modules).
//=================================================================================================



//=================================================================================================
// Section:       GLOBAL FUNCTIONS (PROTOTYPES)
// Description:   Definition of global functions (visible by all modules).
//=================================================================================================

U16   UTIL_u16StringLength( PSZ pszString );
BOOL  UTIL_boCheckStringLength( PSZ pszString, U16 u16MaxLength );
VOID  UTIL_vPuts(  PSZ pszString );

VOID  UTIL_vMemCopy( PVOID pvSource, PVOID pvDest, U16 u16Length );
U32   UTIL_u32MemCopy( PVOID pvSource, PVOID pvDest, U16 u16Length, SDEF_EnByteOrder enByteOrder );
VOID  UTIL_vMemCopyU32( PU32 pu32Source, PU32 pu32Dest, U16 u16Length );
BOOL  UTIL_boMemCompare( PU8 pu8Data1, PU8 pu8Data2, U32 u32Length );
BOOL  UTIL_boMemCompareVal( PU8 pu8Data1, U8 u8Value, U32 u32Length );

U8    UTIL_u8GetPinSource( U16 u16GIPO_Pin );
U8    UTIL_u8DecToBCD( U8 u8Value );
U8    UTIL_u8BCDToDec( U8 u8Value );
VOID  UTIL_vReverseBytes( PU8 pu8Data, U16 u16NumberOfBytes );
U32   UTIL_u32RevU32( U32 u32Data );
U32   UTIL_u32RevFLOAT( FLOAT flData );
U16   UTIL_u16RevU16( U16 u16Data );
U8    UTIL_u8GetNumberOfClkCycles( DOUBLE dtime );

CHAR  UTIL_cGetDeviceRevision( VOID );

U8 UTIL_u8FindMajority( PU8 pu8Data, U16 u16Length );

// printf prototype for debug printf
int fputc( int ch, FILE *f );

#ifdef __cplusplus
}
#endif

#endif
