//-----------------------------------------------------------------------------------//
// Nom du projet 		:	Coursera_Microcontroleur
// Nom du fichier 		:   main_2_9_modifi.c
// Date de création 	:   13.02.2014
// Date de modification : 	22.02.2014
// 
// Auteur 				: 	Philou (Ph. Bovey) 
//
// Description 			: 	utilisation de 8 leds à disposition de la carte Explorer 
//							16 permantant d'afficher si un nombre est paire ou impair 
//							plus son code binaire code sur 7bit (D10(RA7)--> info 
//							pair/impair + D3 à D9(RA0 à RA6) --> info binaire. 
//							donc affichage de valeur de 0 à 127. 		 
//   						deux switches permettent d'incrémenter ou décrémenter la 
//							la valeur. 
//
// 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

#include "antirebond.h"

//--- 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_INC 	PORTDbits.RD13				// entrée digital 
#define SWITCH_S3_DEC 	PORTDbits.RD6				// entrée digital
#define LED_0	 		LATAbits.LATA0				// sortie digital 
#define LED_1	 		LATAbits.LATA1				// sortie digital
#define LED_2	 		LATAbits.LATA2				// sortie digital
#define LED_3	 		LATAbits.LATA3				// sortie digital
#define LED_4	 		LATAbits.LATA4				// sortie digital
#define LED_5	 		LATAbits.LATA5				// sortie digital
#define LED_6	 		LATAbits.LATA6				// sortie digital 
#define LED_P_IM	 	LATAbits.LATA7				// sortie digital => paire = 1 - impaire = 0

//--- déclaration de variables de gloables ---// 
Etat_switch pt_etat_S4; 
Etat_switch pt_etat_S3;

//--- déclaration de prototypes ---// 
void init_in_out(void); 					// configuration des entrées - sorties
void init_leds(void);						// initilisation de l'état des leds au démarrage 
void init_oscillateur(void); 				// configuration oscillateur 
void init_timer1(void); 					// configuration timer 1 
void affichage_led(unsigned char var);  	// activation de led en fonction d'une variable 

//--- programme principale ---//
int main(void)
{
	//--- déclaration de variables ---//
	unsigned char compteur = 0; 

	//--- initialisation ---//
	init_in_out();						// entrées / sorties
	init_oscillateur(); 				// oscillateur 
	init_leds(); 						// permet d'allumer des leds  
	init_timer1(); 						// timer1
	init_antirebond(&pt_etat_S4);  		// pointeur lié à la touche S4
	init_antirebond(&pt_etat_S3);		// pointeur lié à la touche S3 

	//--- boucle sans fin ---//
	while(1)
	{
		//--- test touche incérmentale ---//
		if(switch_presser(&pt_etat_S4))
		{
			//--- test sur le compteur ---// 
			if(compteur < 127)
				compteur++; 
			else 
				compteur = 127;
			
			affichage_led(compteur); 
			reset_info_touche_presser(&pt_etat_S4);
		}

		//--- test touche décrmentale ---// 
		if(switch_presser(&pt_etat_S3))
		{
			//--- test sur le compteur ---//
			if(compteur > 0)
				compteur--; 
			else 
				compteur = 0;
			
			affichage_led(compteur);
			reset_info_touche_presser(&pt_etat_S3);
		}
	}
}

//----------------------------------------------------------------------------------//
//--- 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 
	TRISDbits.TRISD6 = 1; 						// S3 --> switch 	

	//--- configuration sortie numérique ---// 
	TRISAbits.TRISA0 = 0; 						// D3 --> led
	TRISAbits.TRISA1 = 0; 						// D4 --> led
	TRISAbits.TRISA2 = 0; 						// D5 --> led
	TRISAbits.TRISA3 = 0; 						// D6 --> led
	TRISAbits.TRISA4 = 0; 						// D7 --> led
	TRISAbits.TRISA5 = 0; 						// D8 --> led
	TRISAbits.TRISA6 = 0; 						// D9 --> led
	TRISAbits.TRISA7 = 0; 						// D10 --> 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 à 8Mhz ---//
	// utilisation formules du datasheet du DSPic33FJ256GP710A --> page 146
	// quartz utilisé sur le carte = 8MHz = Fin
	// Fcy = Fosc / 2 ; Fosc = Fin(M/(N1 N2))
	// Fin = 8Mhz --> Fosc = 16Mhz --> Fcy = 8Mhz 
	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 	= 6;			// M = 8  

	__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 50ms
//--- 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 --> 8Mhz/256 = 31250Hz --> 32us 
	
	TMR1 = 0; 					// mise à zéro du registre lié au timer 

	PR1 = 1562; 				// période du timer --> 100ms/32us = 1562.5 

	//--- 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; 	    	// désactiver le timer1 au démarrage 
}

//----------------------------------------------------------------------------------//
//--- 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 

	//--- analyse de la touche S4 ---//
	antirebond(&pt_etat_S4, SWITCH_S4_INC);
	//--- analyse de la touche S3 ---//
	antirebond(&pt_etat_S3, SWITCH_S3_DEC); 

	TMR1 = 0; 				// mise à jour du registre de comptage 
	T1CONbits.TON = 1;		// activer à nouveau le Timer 
}

//----------------------------------------------------------------------------------//
//--- nom 				: init_leds
//--- entrée - sortie 	: - / - 
//--- description 		: initialisation des leds lors du démarage  
//--- remarque 			: 
//----------------------------------------------------------------------------------//
void init_leds(void)
{
	//--- déclaration de varaibales ---// 
	double i; 

	//--- allumé toutes les leds ---//
	LATA = 0xFF;						 

	//--- boucle d'attente ---//
	for(i = 0; i < 10000; i++); 

	//--- éteindre toutes les leds ---// 
	LATA = 0x00;						 
}

//----------------------------------------------------------------------------------//
//--- nom 				: affichage_led
//--- entrée - sortie 	: var / - 
//--- description 		: en recevant la valeur d'un variable, les leds vont 
//						  indiquer le code cette valeur de 0 à 127		  
//--- remarque 			: 8bit sont utiliser, le MSB sera utiliser pour savoir si le 
//						  nombre est pair ou non, les 7 autres seront utilisés pour 
//						  afficher la valeur.  
//----------------------------------------------------------------------------------//
void affichage_led(unsigned char var)
{
	//--- test si valeur pair ou impair ---//
	if((var%2) == 0) 
		LED_P_IM = 1; 
	else 
		LED_P_IM = 0;

	LED_0 = (0b0000001 & var); 			// -> bit 0 = x^0 -> 1
	LED_1 = (0b0000010 & var) >> 1;		// -> bit 1 = x^1 -> 2
	LED_2 = (0b0000100 & var) >> 2;		// -> bit 2 = x^2 -> 4
	LED_3 = (0b0001000 & var) >> 3;		// -> bit 3 = x^3 -> 8
	LED_4 = (0b0010000 & var) >> 4;		// -> bit 4 = x^4 -> 16
	LED_5 = (0b0100000 & var) >> 5;		// -> bit 5 = x^5 -> 32
	LED_6 = (0b1000000 & var) >> 6;  	// -> bit 6 = x^6 -> 64 	
}