#include "MyTimer.h"

void (* PtrF ) ( void ) ;  /* déclaration d’un pointeur de fonction */


void MyTimer_Base_Init ( MyTimer_Struct_TypeDef * Timer ) {
	
	if (Timer->Timer == TIM1) RCC->APB2ENR |= RCC_APB2ENR_TIM1EN ; // Active l'horloge locale du périphérique
	if (Timer->Timer == TIM2) RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ;
	if (Timer->Timer == TIM3) RCC->APB1ENR |= RCC_APB1ENR_TIM3EN ;
	if (Timer->Timer == TIM4) RCC->APB1ENR |= RCC_APB1ENR_TIM4EN ;
	
	Timer->Timer->PSC = Timer->PSC; // Réglage de la période du Timer
	Timer->Timer->ARR = Timer->ARR; 
	
	Timer->Timer->CR1 |=  (1 << 0); // Active le compteur
}

void MyTimer_EncoderMode_Conf ( TIM_TypeDef * TIM ) {
	
	TIM->PSC = 0; // Réglage de la période du Timer
	TIM->ARR = 360*4; 
	
// CC1S= ‘01’ (TIMx_CCMR1 register, TI1FP1 mapped on TI1)
	TIM->CCMR1 &= ~TIM_CCMR1_CC1S;
	TIM->CCMR1 |= TIM_CCMR1_CC1S_0;
	
// CC2S= ‘01’ (TIMx_CCMR2 register, TI2FP2 mapped on TI2)
	TIM->CCMR2 &= ~TIM_CCMR1_CC2S;
	TIM->CCMR2 |= TIM_CCMR1_CC2S_0;
	
// CC1P= ‘0’, CC1NP = ‘0’, IC1F =’0000’ (TIMx_CCER register, TI1FP1 noninverted, TI1FP1=TI1)
	TIM->CCER &= ~TIM_CCER_CC1P;
	TIM->CCER &= ~TIM_CCER_CC1NP;
	TIM->CCER &= ~TIM_CCMR1_IC1F;
	
// CC2P= ‘0’, CC2NP = ‘0’, IC2F =’0000’ (TIMx_CCER register, TI2FP2 noninverted, TI2FP2=TI2)
	TIM->CCER &= ~TIM_CCER_CC2P;
	TIM->CCER &= ~TIM_CCER_CC2NP;
	TIM->CCER &= ~TIM_CCMR1_IC2F; // ou CCMR2 ?
	
// SMS= ‘011’ (TIMx_SMCR register, both inputs are active on both rising and falling edges)
	TIM->SMCR &= ~TIM_SMCR_SMS;
	TIM->SMCR |= TIM_SMCR_SMS_0;
	TIM->SMCR |= TIM_SMCR_SMS_1;
	
// CEN = 1 (TIMx_CR1 register, Counter is enabled)
	TIM->CR1 |= TIM_CR1_CEN;
}


void MyTimer_ActiveIT ( TIM_TypeDef * Timer , char Prio , void (* IT_function ) ( void ) ) {
	char num_IT;
	
	PtrF = IT_function; /* affectation du pointeur */
	
	if (Timer == TIM1) num_IT = 25;        // Sélectionne le numéro d'interruption en fonction du timer
	else if (Timer == TIM2) num_IT = 28;
	else if (Timer == TIM3) num_IT = 29;
	else if (Timer == TIM4) num_IT = 30;
	
	Timer->DIER |= (1 << 0); // Valide l'envoi d'une demande d'interruption
	NVIC->IP[num_IT] |= (Prio << 4); // Fixe la priorité de l'interruption dans le NVIC
	NVIC->ISER[0] |= (1 << num_IT); // Autorise la prise en compte de l'interruption dans le NVIC
	
}


void MyTimer_PWM( TIM_TypeDef * Timer , char Channel ) {
	if (Channel == 1) {
		Timer->CCMR1 &= ~TIM_CCMR1_OC1M_0;                   // Mode 1 de la PWM
		Timer->CCMR1 |= TIM_CCMR1_OC1M_1| TIM_CCMR1_OC1M_2;
		Timer->CCER |= TIM_CCER_CC1E;                        // Validation de la sortie du canal
	}
	else if (Channel == 2) {
		Timer->CCMR1 &= ~TIM_CCMR1_OC2M_0;
		Timer->CCMR1 |= TIM_CCMR1_OC2M_1| TIM_CCMR1_OC2M_2;
		Timer->CCER |= TIM_CCER_CC2E;
	}
	else if (Channel == 3) {
		Timer->CCMR2 &= ~TIM_CCMR2_OC3M_0;
		Timer->CCMR2 |= TIM_CCMR2_OC3M_1| TIM_CCMR2_OC3M_2;
		Timer->CCER |= TIM_CCER_CC3E;
	}
	else if (Channel == 4) {
		Timer->CCMR2 &= ~TIM_CCMR2_OC4M_0;
		Timer->CCMR2 |= TIM_CCMR2_OC4M_1| TIM_CCMR2_OC4M_2;
		Timer->CCER |= TIM_CCER_CC4E;
	}
}	
	
void Set_Duty_Cycle (TIM_TypeDef * Timer, char Channel, char Duty_Cycle) {
	if (Channel == 1) {
		Timer->CCR1 = (int) (Timer->ARR)*Duty_Cycle/100;
	}
	else if (Channel == 2) {
		Timer->CCR2 = (int) (Timer->ARR)*Duty_Cycle/100;
	}
	else if (Channel == 3) {
		Timer->CCR3 = (int) (Timer->ARR)*Duty_Cycle/100;
	}
	else if (Channel == 4) {
		Timer->CCR4 = (int) (Timer->ARR)*Duty_Cycle/100;
	}
}




/********************************************
****              HANDLERS               ****
********************************************/

void TIM1_UP_IRQHandler ( void )
{
	TIM1->SR &= ~(1 << 0); // Remet à 0 le flag d'interruption
	if (PtrF != 0)
		(*PtrF) (); /* appel indirect de la fonction */
}


void TIM2_IRQHandler ( void )
{
	//TIM2->SR &= ~(1 << 0);
	TIM2->SR &= ~TIM_SR_UIF;
	if (PtrF != 0)
		(*PtrF) (); /* appel indirect de la fonction */
}


void TIM3_IRQHandler ( void )
{
	TIM3->SR &= ~(1 << 0);
	if (PtrF != 0)
		(*PtrF) (); /* appel indirect de la fonction */
}


void TIM4_IRQHandler ( void )
{
	TIM4->SR &= ~(1 << 0);
	if (PtrF != 0)
		(*PtrF) (); /* appel indirect de la fonction */
}

