/*************************************************************
 * Christophe Le Lann <totofwebcreation@gmail.com>
 * http://www.totofweb.ma.cx
 *
 * Ce programme utilise le module CCP1 pour sortie un signal
 * PWM à 50KHz
 *
 * VOIR COURS DE BIGONOFF (PARTIE 2)
 *
 * Formules utiles :
 * PR2 = Temps_cycle / (Prediviseur * 4 * Temps_oscillation) -1 = 99
 * (PR2 est la valeur de déclenchement de l'interruption sur TMR2)
 * Ref = Temps_haut / (Prediviseur * Temps_oscillation) = 200
 * Ref est la valeur de TMR2 pour laquelle on revient à l'état bas
 * Ref est contenue dans CCPR1L pour les bits avant la virgule,
 * plus deux bits après la virgule, DC1B1 et DC1B0 dans CCP1CON
 *************************************************************/

/****************************************
 * Configuration du compilateur
 ****************************************/

// Quartz de 20MHz (utilisé pour les délais)
#pragma CLOCK_FREQ 20000000

/****************************************
 * Registres spéciaux
 ****************************************/
char PIR1    @ 0x0c;
char TMR2    @ 0x11;
char CCPR1L  @ 0x15;
char CCP1CON @ 0x17;
char TRISC   @ 0x87;
char PORTC   @ 0x07;
char PIE1    @ 0x8c;
char PR2     @ 0x92;
char T2CON   @ 0x12;

/****************************************
 * Interruptions
 ****************************************/

void interrupt() {
	if (PIR1 & 00000010b) {				// Interruption sur TIMER2
		TMR2 = 0;						// Remise à 0 du TIMER2 pour compter jusqu'à la prochaine interruption (quand TMR2 = PR2)
		clear_bit(PIR1,1);				// Efface le flag d'interruption
	}
}

/****************************************
 * Programme principal
 ****************************************/

void main() {

	PR2 = 99;							// Valeur que TMR2 doit atteindre pour déclencher l'interruption
	CCPR1L = 0;							// Valeur de TMR2 pour laquelle on remet la pin à l'état bas (impérativement CCPR1L < PR2)
	clear_bit(CCP1CON,5);				// Chiffre après la virgule de CCPR1L
	clear_bit(CCP1CON,4);				// 2e chiffre après la virgule de CCPR1l

	TRISC = 00000000b;					// CCP1 en sortie

	TMR2 = 0;
	enable_interrupt(GIE);				// Les interruptions sont activées
	set_bit(PIE1,1);					// Activation des interruptions sur TIMER2
	T2CON = 00000100b;					// Prescaler = 0; Postscaler = 0; Timer2 On bit = 1

	set_bit(CCP1CON,3);					// Config de CCP1 en mode PWM
	set_bit(CCP1CON,2);					// Config de CCP1 en mode PWM
	clear_bit(CCP1CON,1);				// Config de CCP1 en mode PWM
	clear_bit(CCP1CON,0);				// Config de CCP1 en mode PWM



	while (1);							// Boucle infinie
		for (CCPR1L = 1; CCPR1L < 99; CCPR1L++) // On fait varier la commande de 1 à 99 par pas de 200ms
			delay_ms(200);
}

