/**
**************************************************************************************************
* @file		timer.h
* @author	Kerem Yollu & Edwin Koch
* @date		19.12.2021
* @version	1.0
************************************************************************************************** 
* @brief	This is the genral interface for timers.
* 
* **Detailed Description :**
* This the timer interface and belongs to the interface layer
*
* @todo 06.03.22 Following functions are to be implmented : timerSetHz / timerSetMs / timerSetNs / timerSetPs
* @todo 27.03.22 Add Compare capture modules compare/capture/ register set value in function timerInitOutputCompare(); 
**************************************************************************************************
*/

#ifndef _TIMER_H_
#define _TIMER_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "hardwareDescription.h"
#include "pin.h"

/*! Emun of possible Timer Errors */ 
typedef enum {
	functionNotSupported,	/*!< This Funtion is not awailable on this **HARDWARE** */
	prescalerOutOfRange,	/*!< Set prescaler value exeeds the Register's **HARDWARE** size */
	ccChannelNoOutOfRange	/*!< The Selecter internal Capture/Compare timer cahnnel is not given by the **HARDWARE** size */
} timerError_t;

/*! Enum of possible counting modes */
typedef enum {
	upCounting,	/*!< Counter is in upcounting mode */
	downCounting /*!< Counter is in downcounting mode */
} timerCountDirection_t;

/*! Enum of possible timer modes */
typedef enum {
	counter,		/*!< Timer is in counting mode */
	inputCapture,	/*!<  */
	outputCompare,	/*!<  */
	onePulse		/*!<  */
} timerMode_t;

/*! 
 * Output compare modes.
 */
typedef enum {
	frozen, /*!< Pin update is **de-activated** even when a compare match happens */  
	high_on_match, /*!< Pin goes **high** when a compare match occurs */
	low_on_match, /*!< Pin goes **low** when a compare match occurs */
	toggle, /*!< Pin **toggles** when a compare match occurs */
	inactive_force_high, /*!< Pin if forced **high** */
	inactive_force_low, /*!< Pin if forced **low** */
	pwm_normal, /*!< Standart PWM mode */ 
	pwm_inverted /*!< Inverted PWM mode */
} timerOutputCompareMode_t ;

/*! 
 * @brief Reset the timer to its default state
 * @param timer The handle of the desired timer
 */
void timerReset(timerNo_t timer);
/*!
 *	@brief Activate the bus on which the desired timer is connected to
 *	@param timer The handle of the desired timer
 */
void timerActivateBus(timerNo_t timer); 
/*!
 *	@brief Enable the timer
 *	@param timer The handle of the desired timer	
 */
void timerEnable(timerNo_t timer); 

/*!
 *	@brief Disable the timer
 *	@param timer The handle of the desired timer	
 */
void timerDisable(timerNo_t timer);

/*!
 *	@brief Set the operation mode of the timer
 *	@param timer The handle of the desired timer
 *	@param mode The desired operation mode 	
 */
void timerSetMode(timerNo_t timer, timerMode_t mode);

/*!
 *	@brief Set the timer conting direction	
 *	@param timer The handle of the desired timer
 *	@param direction Counting direction	
 */
void timerSetCountDirection(timerNo_t timer, timerCountDirection_t direction); 

/*! 
 * @brief Sets the given timer's prescaler value. 
 *
 * This fucntion will also check if the entered prascaler value exeeds the register size.
 * If violated the prescalerOutOfRange Error will be generated. 
 *
 *	@param timer The handle of the desired timer
 *	@param prescaler The prescaler value for the timer
 */
void timerSetPrescaler(timerNo_t timer, uint32_t prescaler);

/*!
 *	@brief Set the postscaler of the timer
 *
 *	This function will throw an error when the postscaler value exceeds the hardware register 
 *	size.
 *
 *	@param timer The handle of the desired timer
 *	@param postscaler The postscaler value
 */
void timerSetPostscaler(timerNo_t timer, uint32_t postscaler);

/*!
 *	@brief Set the outoreload value of the timer
 *	@param timer The handle of the desired timer	
 *	@param reload The reload value
 */
void timerSetAutoReload(timerNo_t timer, uint32_t reload); 
uint8_t timerGetUpdateInterrupt(timerNo_t timer); 
void timerClearUpdateInterrupt(timerNo_t timer);
void timerClearCounter(timerNo_t timer); 

/* Second stage configuration */

/*!
 * @brief Initializes the counter of the timer
 *
 * @param timer The desired timer
 * @param prescaler the prescaler value for the counter clock
 * @param autoReload The autoreload value for the counter
 * @param direction The counter direction
 *
 */
void timerInitCounter( timerNo_t timer, 
						uint32_t prescaler, 
						uint32_t autoReload, 
						timerCountDirection_t direction);

/*!
 * This funtion is not implemented yet. Will be used to implment pwm functionality of the timer.
 */
void timerInitPwm( timerNo_t timer, 
						uint32_t prescaler, 
						uint32_t period, 
						timerCountDirection_t direction);


/*!
 * @brief Sets the Timer to the desired compare mode The function timerInitCounter(); Should be 
 * called before to init the Timer. 
 *	Calling this function will stop the timer and clear the counter. 
 *
 * @param timer The desired timer number
 * @param mode The desired output compare mode
 * @param timerIoChannel The internal Timer Capture compare channel to be used.
 * @param pinNo The desired Pin Number to be used as outpujt
 * @param altFuntion The Alternate funtion No for the given Pin
 * @param polarity Sets the the given Pin
 * @param ccValue Capture Compare Value
 */
void timerInitOutputCompare( timerNo_t timer, 
						timerOutputCompareMode_t mode,
						uint8_t timerIoChannel, 
						pinNo_t pinNo, 
						uint16_t altFunction,
						uint8_t polarity,
						uint32_t ccValue);
/*!
 * @brief Sets the counter compare calue of the desired timer io channel 
 *
 * @param timer The desired timer number
 * @param timerIoChannel The internal Timer Capture compare channel to be used.
 * @param ccValue Capture Compare Value
 */
void timerSetCounterCompareValue(timerNo_t  timer,
								  uint8_t timerIoChannel,
								  uint32_t ccValue);


/*!
 *	@brief Set the outoreload value of the timer
 *
 *	The following calculation is performed.
 *
 *	\f$ f_{timer} = \frac{ BusClock }{ (Prescaler - 1 ) \cdot ( Period - 1 )} \f$
 *
 *	The values of \f$ Period \f$ (Reload Value) and \f$ Prescaler \f$ will be calculated to match
 *	or come close to the desired timer frequency \f$ f_{timer} \f$.
 *
 *	@param timer The handle of the desired timer	
 *	@param hz The desired frequency in Hz
 */
void timerSetHz(timerNo_t timer, uint16_t hz); 
void timerSetMs(timerNo_t timer, uint16_t ms); 
void timerSetNs(timerNo_t timer, uint16_t ns); 
void timerSetPs(timerNo_t timer, uint16_t ps); 

/*!
 * @brief Enables the timer  
 * @param timer The desired timer number
 */
void timerSart(timerNo_t timer);

/*!
 * @brief Disables the timer  
 * @param timer The desired timer number
 */
void timerHalt(timerNo_t timer);

/*!
 * @brief Halts the timer and then clears the counter.  
 * @param timer The desired timer number
 */
void timerStop(timerNo_t timer);

uint32_t timerGetCount(timerNo_t timer);

void timerThrowError(timerError_t error); 

#ifdef __cplusplus
}
#endif

#endif // _TIMER_H_
