#include "MyTimer.h"
#include "stm32f10x.h"
#include "Driver_GPIO.h"
#define NULL 0

// D�claration des fonctions utilis�es lors de handlers
void (* ptr1) (void) = NULL;
void (* ptr2) (void) = NULL;
void (* ptr3) (void) = NULL;
void (* ptr4) (void) = NULL;
	
void MyTimer_Base_Init (MyTimer_Struct_TypeDef* Data){
	TIM_TypeDef * numTimer ;
	numTimer = Data->Timer ;
	switch ((int)numTimer) { // on cast le pointeur vers le timer pour le comparer au pointeur des timers existants
		case (int)TIM1 :
			RCC->APB2ENR |= RCC_APB2ENR_TIM1EN ; // masque pour activer le timer (0xOB, pin 11)
		break ;
		
		case (int)TIM2:
			RCC->APB1ENR |= RCC_APB1ENR_TIM2EN ; // masque pour activer le timer2 (0x01)
		break ;
		
		case (int)TIM3:
			RCC->APB1ENR |= RCC_APB1ENR_TIM3EN ; // masque pour activer le timer2 (0x02)
		break ;
		
		case (int)TIM4:
			RCC->APB1ENR |= RCC_APB1ENR_TIM4EN ; // masque pour activer le timer2 (0x03)
		break ;
	}
	// on parametre ARR et PSC sur le timer
	Data->Timer->ARR = Data->ARR ;
	Data->Timer->PSC = Data->PSC ;
}

void MyTimer_Base_Start(TIM_TypeDef * Timer ) {
	Timer -> CR1 |= TIM_CR1_CEN ; // on active la clock du  timer
}

void MyTimer_Base_Stop(TIM_TypeDef * Timer ) {
		Timer -> CR1 &= ~TIM_CR1_CEN ; // on d�sactive la clock du timer
}


uint16_t Get_Timer_Count(TIM_TypeDef * Timer){
	return Timer ->CNT;
}
void MyTimer_ActiveIT ( TIM_TypeDef * Timer , char Prio, void (* IT_function) (void)){
	Timer->DIER |= 0x01; // on autorise l'interuption au niveau du timer

	switch ((int)Timer) { // on cast le timer pour le comparer au pointeur des timers existants
		case (int)TIM1 :
			NVIC->ISER[0] |= NVIC_ISER_SETENA_25; // on autorise l'interuption au niveau du coeur par le timer 1
			NVIC->IP[25] = Prio; // on parametre la prio du timer
			ptr1 = IT_function; //fonction � appeler par le handler
		break ;
		
		case (int)TIM2:
			NVIC->ISER[0] |= NVIC_ISER_SETENA_28;  // on autorise l'interuption au niveau du coeur par le timer 2
			NVIC->IP[28] = Prio; // on parametre la prio du timer
			ptr2 = IT_function; //fonction � appeler par le handler
		break ;
		
		case (int)TIM3:
			NVIC->ISER[0] |= NVIC_ISER_SETENA_29;  // on autorise l'interuption au niveau du coeur par le timer 3
			NVIC->IP[29] = Prio; // on parametre la prio du timer
			ptr3 = IT_function; //fonction � appeler par le handler			
		 break ;
		
		case (int)TIM4:
			NVIC->ISER[0] |= NVIC_ISER_SETENA_30;  // on autorise l'interuption au niveau du coeur par le timer 4
			NVIC->IP[30] = Prio; // on parametre la prio du timer
			ptr4 = IT_function; //fonction � appeler par le handler
		break ;
	}
}
	


void TIM1_UP_IRQHandler(void){
	if (ptr1 != NULL){ // si la fonction a bien �t� initialis�e
		(*ptr1)(); // on appelle la fonction en cas de handler1
	}
	TIM1->SR &= ~(1<<0); // on baisse le flag d'activation
}

void TIM2_IRQHandler(void){
	if (ptr2 != NULL){ // si la fonction a bien �t� initialis�e
		(*ptr2)(); // on appelle la fonction en cas de handler2
	}
	TIM2->SR &= ~(1<<0); // on baisse le flag d'activation
}

void TIM3_IRQHandler(void){
	if (ptr3 != NULL){ // si la fonction a bien �t� initialis�e
		(*ptr3)(); // on appelle la fonction en cas de handler3
	}
	TIM3->SR &= ~(1<<0); // on baisse le flag d'activation
}

void TIM4_IRQHandler(void){
	if (ptr4 != NULL){ // si la fonction a bien �t� initialis�e
		(*ptr4)(); // on appelle la fonction en cas de handler4
	}
	TIM4->SR &= ~(1<<0); // on baisse le flag d'activation
}
	
void MyTimer_PWM(TIM_TypeDef * Timer, char Channel){
	MyGPIO_Struct_TypeDef gpio;	
	gpio.GPIO_Conf = AltOut_Ppull;
	
	// Activation la capture du compteur (CNT) dans le registre capture register
	Timer->CCER |= TIM_CCER_CC1E;
	
	
	
	switch ((int)Channel) { // on cast le timer pour le comparer au pointeur des timers existants
		/* ==============
		=== Channel 1 ===
		============== */
		
		case 1 :	
			// On veut mettre les bits 4 � 6 de OC1M � 110 (PWM mode 1 p 349)
			Timer->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
			Timer->CCMR1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC1S); // mettre 00
			Timer->CCR1 = 0;
		
			switch ((int)Timer) { // on cast le timer pour le comparer au pointeur des timers existants
				case (int)TIM1 :
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 8;
					TIM1->BDTR |= TIM_BDTR_MOE ; // bit MOE pour activer le timer g�n�ralement (main output enable)
				break ;
				
				case (int)TIM2:
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 0;
				break ;
				
				case (int)TIM3:
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 6;
				break ;
				
				case (int)TIM4:
					gpio.GPIO = GPIOB;
					gpio.GPIO_Pin = 6;
				break ;
			}
		break ;
		
				
		/* ==============
		=== Channel 2 ===
		============== */
						
		case 2 :
			
			// On veut mettre les bits 12 � 14 de OC1M � 110 (PWM mode 1 p 349)
			Timer->CCMR1 |= TIM_CCMR1_OC2M_1| TIM_CCMR1_OC2M_2;
			Timer->CCMR1 &= ~(TIM_CCMR1_CC2S | TIM_CCMR1_CC2S); // mettre 00
			Timer->CCR2 = 0;
			
			switch ((int)Timer) { // on cast le timer pour le comparer au pointeur des timers existants
				case (int)TIM1 :
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 9;
					TIM1->BDTR |= TIM_BDTR_MOE ; // bit MOE pour activer le timer g�n�ralement (main output enable)
				break ;
				
				case (int)TIM2:
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 1;
				break ;
				
				case (int)TIM3:
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 7;
				break ;
				
				case (int)TIM4:
					gpio.GPIO = GPIOB;
					gpio.GPIO_Pin = 7;
				break ;
			}
		break ;
				
		
		/* ==============
		=== Channel 3 ===
		============== */
		case 3 :
			
			// On veut mettre les bits 4 � 6 de OC2M � 110 (PWM mode 1 p 349)
			Timer->CCMR2 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
			Timer->CCMR2 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC1S); // mettre 00
			Timer->CCR3 = 0;
		
			switch ((int)Timer) { // on cast le timer pour le comparer au pointeur des timers existants
				case (int)TIM1 :
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 10;
					TIM1->BDTR |= TIM_BDTR_MOE ; // bit MOE pour activer le timer g�n�ralement (main output enable)
				break ;
				
				case (int)TIM2:
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 2;
				break ;
				
				case (int)TIM3:
					gpio.GPIO = GPIOB;
					gpio.GPIO_Pin = 0;
				break ;
				
				case (int)TIM4:
					gpio.GPIO = GPIOB;
					gpio.GPIO_Pin = 8;
				break ;
			}
		break ;
				
		/* ==============
		=== Channel 4 ===
		============== */
		case 4 :
			
			// On veut mettre les bits 12 � 14 de OC2M � 110 (PWM mode 1 p 349)
			Timer->CCMR2 |= TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2;
			Timer->CCMR2 &= ~(TIM_CCMR1_CC2S | TIM_CCMR1_CC2S); // mettre 00
			Timer->CCR4 = 0;
		
			switch ((int)Timer) { // on cast le timer pour le comparer au pointeur des timers existants
				case (int)TIM1 :
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 11;
					TIM1->BDTR |= TIM_BDTR_MOE ; // bit MOE pour activer le timer g�n�ralement (main output enable)
				break ;
				
				case (int)TIM2:
					gpio.GPIO = GPIOA;
					gpio.GPIO_Pin = 3;
				break ;
				
				case (int)TIM3:
					gpio.GPIO = GPIOB;
					gpio.GPIO_Pin = 1;
				break ;
				
				case (int)TIM4:
					gpio.GPIO = GPIOB;
					gpio.GPIO_Pin = 9;
				break ;
			}
		break ;
	}
	MyGPIO_Init(&gpio);
}

// calculer et definir les valeurs de CRR
void Set_PWM_PRCT(TIM_TypeDef * Timer, char Channel, int percent){
	short value = Timer->ARR*percent/100;
	
	switch (Channel){
		case 1:
			Timer->CCR1 = value;
		break;
		case 2:
			Timer->CCR2 = value;
		break;
		case 3:
			Timer->CCR3 = value;
		break;
		case 4:
			Timer->CCR4 = value;
		break;
	}
	
	
	
	
}
void Set_Duty_Cycle(TIM_TypeDef * Timer , char Channel,uint16_t crr){
	switch(Channel){
		case 1:
			Timer->CCR1 = crr;
			break;
		case 2:
			Timer->CCR2 = crr;
			break;
		case 3:
			Timer->CCR3 = crr;
			break;
		case 4:
			Timer->CCR4 = crr;
			break;
	}
}


uint16_t Get_Max_Duty(TIM_TypeDef * Timer){
	return Timer->ARR;
}







