//-----------------------------------------------------------------------------------//
// Nom du projet 		:	Coursera_Microcontroleur
// Nom du fichier 		:   main_2_5.c
// Date de création 	:   09.01.2014
// Date de modification : 	17.01.2014
// 
// Auteur 				: 	Philou (Ph. Bovey) 
//
// Description 			: 	utilisation bouton poussoir (actif état bas) --> S4(RD13) 
//							si maintient le bouton enfoncé, une led doit clignoté à   
//						    une fréquence 2Hz (soit 500ms) --> D3 (RA0) 
//
// Remarques			: 
// 	    chemin pour trouver le headerfile 
//		C:\Program Files\Microchip\MPLAB C30\support\dsPIC33F\h
//
//	    doc pour le DSP : 
//		http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en546064
// 
//----------------------------------------------------------------------------------//
//--- librairie à inclure ---// 
#if defined(__dsPIC33F__)
#include "p33Fxxxx.h"
#endif

//--- Fusibles ---//
_FOSCSEL(FNOSC_PRI); 								// utilisation du quartz de 8MHz externe 
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF  & POSCMD_XT); 	// pin OS2 garder pour l'horlohe 
													// oscillateur XT	
_FWDT(FWDTEN_OFF); 									// ne pas activer le watchdog

//--- definition ---// 
#define SWITCH_S4 	PORTDbits.RD13					// entrée 
#define LED_3 		LATAbits.LATA0					// sortie 

//--- déclaration de variables de gloables ---// 
int compteur = 0 ;
int inverse_etat = 0;  

//--- déclaration de prototypes ---// 
void init_in_out(void); 				// configuration des entrées - sorties
void init_oscillateur(void); 			// configuration oscillateur  
void init_timer1(void); 				// configuration timer 1 


//--- programme principale ---//
int main(void)
{
	//--- initialisation ---//
	init_in_out();				// entrées / sorties
	init_oscillateur(); 		// oscillateur 
	init_timer1(); 				// timer1 

	//--- allumer la led au démarrage ---//
	LED_3 = 1; 

	//--- boucle sans fin ---//
	while(1)
	{
		//--- maintient de la touche S4 enfoncé 
		while(SWITCH_S4 == 0)
		{
			//--- permet un changement d'état toutes les 500ms secondes ---//
			if(inverse_etat == 1)
				LED_3  = ~LED_3;  	 
		}
		//--- si S4 pas appuyer reste allumée ---//  
		LED_3 = 1;	
	}
}


//----------------------------------------------------------------------------------//
//--- nom 				: init_in_out
//--- entrée - sortie 	: - / - 
//--- description 		: initialisation IN/OUT ANAL/NUM --> 
//--- remarque 			: doc = section 10 
//----------------------------------------------------------------------------------//
void init_in_out(void)
{	
	//--- configuration entrée analogique ---// 

	//--- configuration entrée numérique ---// 
	TRISDbits.TRISD13 = 1; 						// S4 --> switch  	

	//--- configuration sortie numérique ---// 
	TRISAbits.TRISA0 = 0; 						// D3 --> led
}


//----------------------------------------------------------------------------------//
//--- nom 				: init_oscillateur
//--- entrée - sortie 	: - / - 
//--- description 		: configuration oscillateur | clock à choix  
//-- remarque 			: doc = section 7
//----------------------------------------------------------------------------------//
void init_oscillateur(void)
{
	//--- configuration de l'oscillateur interne à 40Mhz ---//
	// utilisation formules du datasheet du DSPic33FJ256GP710A --> page 146
	// Fcy = Fosc / 2 ; Fosc = Fin(M/(N1 N2))
	// Fin = 8Mhz --> Fosc = 40Mhz --> Fcy = 40Mhz 
	OSCCONbits.COSC 	= 3;			// sélection de l'oscillateur XT 
	OSCCONbits.CLKLOCK	= 0;			// l'horloge et la PLL peuvent être modifié 	
	
	CLKDIVbits.ROI	= 0; 				// pas d'effet si il y a interruption 
	CLKDIVbits.DOZE	= 0; 				// pas de réduction sur l'horloge Fcy /1
	CLKDIVbits.DOZEN	= 0; 		
	CLKDIVbits.PLLPRE 	= 0; 			// N1 = 2	
    CLKDIVbits.PLLPOST 	= 0; 			// N2 = 2 	
	
	PLLFBDbits.PLLDIV 	= 38;			// M = 40  

	__builtin_write_OSCCONH(0x03); 		// fonction appelant du code assembleur 
										// configuration du registre NOSC (OSCCON) --> 
										// 011 = Primary Oscillator with PLL (XTPLL, HSPLL, ECPLL)
	__builtin_write_OSCCONL(0x01);		// Active la commutation de la clock
	while(OSCCONbits.COSC != 0b011); 	//
}


//----------------------------------------------------------------------------------//
//--- nom 				: init_timer1
//--- entrée - sortie 	: - / - 
//--- description 		: initialisation timer 1 pour avoir une horloge de 100ms
//--- remarque 			: doc = section 11 
//----------------------------------------------------------------------------------//
void init_timer1(void)
{
	//--- registre de configuration du Timer1 ---//
	T1CONbits.TON = 0; 			// désactiver le timer pour la configuration 
	T1CONbits.TCS = 0; 			// clock interne
	T1CONbits.TSYNC = 0; 		// synchroniser la clock externe 	
	T1CONbits.TCKPS = 3; 		// prédivseur régler à 256 --> 40Mhz/256 = 156250Hz --> 6.4us 
	
	TMR1 = 0; 					// mise à zéro du registre lié au timer 

	PR1 = 15625; 				// période du timer --> 100ms/6.4us = 15625 

	//--- registres des configurations des interruptions liées au Timer1 ---//
	IPC0bits.T1IP = 7; 			// choix de la priorité --> ici la plus élevée 7 = 111
	IFS0bits.T1IF = 0; 			// remise à zéro de l'interruption 
	IEC0bits.T1IE = 1; 			// activation de l'interruption lié au Timer1 

	T1CONbits.TON = 1; 			// activer le timer1
}

//----------------------------------------------------------------------------------//
//--- nom 				: _T1Interrupt
//--- entrée - sortie 	: - / - 
//--- description 		: interruption liée au  
//----------------------------------------------------------------------------------//
void __attribute__((interrupt,no_auto_psv)) _T1Interrupt( void )
{
	IFS0bits.T1IF = 0; 		// remise à zéor du flag d'interruption 

	//--- prend l'état inverse de l'état présédent ---//
	if(compteur >= 4)
	{
		inverse_etat = 1;
		compteur = 0; 
	}
	else 
	{
		compteur++;
		inverse_etat = 0;
	} 

	TMR1 = 0; 
	T1CONbits.TON = 1;		// activer à nouveau le Timer 
}