#include <18F252.h>										// Inclusion du Header correspondant au µC utilisé
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP				// Paramétrage des fusibles du microcontrôleur
#use delay(clock=10000000)
#use rs232(baud=57600, xmit=PIN_C6,rcv=PIN_C7)

//******************************
// Defines
//******************************
#define MOT_D_AV   PIN_B4
#define MOT_D_AR   PIN_B3
#define MOT_G_AV   PIN_B1
#define MOT_G_AR   PIN_B2
#define LED_JAUNE  PIN_C3
#define LED_VERTE  PIN_C1
#define REC_IR     PIN_A0
#define CODEIR_AV  0x14bf								// Avant (touche TAPE)
#define CODEIR_AR  0x1820								// Arrière (touche PROG+)
#define CODEIR_ST  0x040f								// Stop (touche DSC)
#define CODEIR_RG  0x0c06								// Rotation gauche (touche DBB)
#define CODEIR_RD  0x0400								// Rotation droite (touche SURR)
#define CODEIR_VG  0x1d7f								// Virage gauche (touche VIDEO)
#define CODEIR_VD  0x147f								// Virage droite (touche TUNER)
#define CODEIR_ARG 0x1821								// Virage gauche en arrière (touche PROG-)
#define CODEIR_ARD 0x183f/								/ Virage droite en arrière (touche TV)
#define CODEIR_UP  0x1410								// Augmenter la vitesse (touche VOL+)
#define CODEIR_DWN 0x1c11								// Diminuer la vitesse (touche VOL-)

//******************************
// Variables globales
//******************************
int mot_commande[] = {0, 0, 0, 0};						// {MOT_D_AV, MOT_D_AR, MOT_G_AV, MOT_G_AR} [0, 10]
int mot_effectue = 10;									// [0, 10]
int vitesse = 5;

//******************************
// Fonctions
//******************************

void led_verte_on() {
	output_high(LED_VERTE);
}
void led_verte_off() {
	output_low(LED_VERTE);
}
void led_jaune_on() {
	output_high(LED_JAUNE);
}
void led_jaune_off() {
	output_low(LED_JAUNE);
}
void mot_generation_pwm() {								// toutes les 3.2ms 1/(20000000/4/64/250)

	led_jaune_on();

	if (mot_effectue >= 10) {
		mot_effectue = 0;

		if (mot_commande[0] > 0)						// Moteur droit vers l'avant
			output_high(MOT_D_AV);
		else {
			output_low(MOT_D_AV);
			if (mot_commande[1] > 0)					// Moteur droit vers l'arrière
				output_high(MOT_D_AR);
			else
				output_low(MOT_D_AR);
		}
		if (mot_commande[2] > 0)						// Moteur gauche vers l'avant
			output_high(MOT_G_AV);
		else {
			output_low(MOT_G_AV);
			if (mot_commande[3] > 0)					// Moteur gauche vers l'arrière
				output_high(MOT_G_AR);
			else
				output_low(MOT_G_AR);
		}
	} else {
		if (mot_commande[0] > 0 && mot_effectue >= mot_commande[0])
			output_low(MOT_D_AV);
		if (mot_commande[1] > 0 && mot_effectue >= mot_commande[1])
			output_low(MOT_D_AR);
		if (mot_commande[2] > 0 && mot_effectue >= mot_commande[2])
			output_low(MOT_G_AV);
		if (mot_commande[3] > 0 && mot_effectue >= mot_commande[3])
			output_low(MOT_G_AR);
	}

	mot_effectue++;										// Comptage des timers écoulés

	led_jaune_off();

}
void mot_avancer() {
	printf("en avant !\n\r");
	mot_commande[0] = vitesse;							// Moteur droit avance
	mot_commande[1] = 0;
	mot_commande[2] = vitesse;							// Moteur gauche avance
	mot_commande[3] = 0;
}
void mot_reculer() {
	printf("en arriere !\n\r");
	mot_commande[0] = 0;
	mot_commande[1] = vitesse;							// Moteur droit recule
	mot_commande[2] = 0;
	mot_commande[3] = vitesse;							// Moteur gauche recule
}
void mot_arreter() {
	printf("stop !\n\r");
	mot_commande[0] = 0;								// Moteur droit à l'arrêt
	mot_commande[1] = 0;
	mot_commande[2] = 0;								// Moteur gauche à l'arrêt
	mot_commande[3] = 0;
}
void mot_virage_droite() {
	printf("virage a droite !\n\r");
	mot_commande[0] = 0;								// Moteur droit à l'arrêt
	mot_commande[1] = 0;
	mot_commande[2] = vitesse;							// Moteur gauche avance
	mot_commande[3] = 0;
}
void mot_virage_gauche() {
	printf("virage a gauche !\n\r");
	mot_commande[0] = vitesse;							// Moteur droit avance
	mot_commande[1] = 0;
	mot_commande[2] = 0;								// Moteur gauche à l'arrêt
	mot_commande[3] = 0;
}
void mot_rotation_droite() {
	printf("rotation a droite !\n\r");
	mot_commande[0] = 0;
	mot_commande[1] = vitesse;							// Moteur droit recule
	mot_commande[2] = vitesse;							// Moteur gauche avance
	mot_commande[3] = 0;
}
void mot_rotation_gauche() {
	printf("rotation a gauche !\n\r");
	mot_commande[0] = vitesse;							// Moteur droit avance
	mot_commande[1] = 0;
	mot_commande[2] = 0;
	mot_commande[3] = vitesse;							// Moteur gauche recule
}
void mot_arriere_gauche() {
	printf("virage a gauche en arriere !\n\r");
	mot_commande[0] = 0;								// Moteur droit recule
	mot_commande[1] = vitesse;
	mot_commande[2] = 0;
	mot_commande[3] = 0;								// Moteur gauche à l'arrêt
}
void mot_arriere_droite() {
	printf("virage a droite en arriere !\n\r");
	mot_commande[0] = 0;								// Moteur droit à l'arrêt
	mot_commande[1] = 0;
	mot_commande[2] = 0;
	mot_commande[3] = vitesse;							// Moteur gauche recule
}
void vitesse_up() {
	printf("augmenter la vitesse !\n\r");
	if (vitesse < 10) {
		vitesse++;
	if (mot_commande[0] > 0)
		mot_commande[0] = vitesse;
	if (mot_commande[1] > 0)
		mot_commande[1] = vitesse;
	if (mot_commande[2] > 0)
		mot_commande[2] = vitesse;
	if (mot_commande[3] > 0)
		mot_commande[3] = vitesse;
	}
}
void vitesse_down() {
	printf("diminuer la vitesse !\n\r");
	if (vitesse > 1) {
		vitesse--;
	if (mot_commande[0] > 0)
		mot_commande[0] = vitesse;
	if (mot_commande[1] > 0)
		mot_commande[1] = vitesse;
	if (mot_commande[2] > 0)
		mot_commande[2] = vitesse;
	if (mot_commande[3] > 0)
		mot_commande[3] = vitesse;
	}
}


//******************************
// Interruptions
//******************************

#INT_TIMER0
void interrupt_timer0() {
	mot_generation_pwm();
	set_timer0(65281);
}

void config_interrupt() {

	// Timer 0
	set_timer0(65281);
	setup_timer_0(RTCC_INTERNAL);
	enable_interrupts(INT_TIMER0);

	enable_interrupts(GLOBAL);
}

//******************************
// Programme principal
//******************************

void main () {

	int1 bit;
	int i, nbit, erreur;
	byte buffer[2];
	int16 commande;

	delay_ms(500);

	config_interrupt();

	printf ("Demarrage recepteur telecommande IR PHILIPS\r\n\n");

	while (TRUE) {

		buffer[0] = 0;
		buffer[1] = 0;
		erreur = 0;
		nbit = 0;
		i = 0;

		while (i++ != 4) { // Test si REC_IR au repos prolongé
			if (input(REC_IR) == 0)
				i = 0;
			delay_us(889);
		}


		while (input(REC_IR) == 1); // Attend bit de START

		disable_interrupts(GLOBAL);

		delay_us(444); // on se positionne au milieu


		led_verte_on();

		while ((nbit++ != 13) && (erreur == 0)) {
			delay_us (889);

			if (input(REC_IR) == 0) {
				delay_us(889);
				if (input(REC_IR) != 1)
					erreur = 1;
				bit = 0; // c'est un 0
			} else {
				delay_us(889);
				if (input(REC_IR) != 0)
					erreur = 1;
				bit = 1;
			}
			shift_left(buffer, 2, bit); // et on le pousse dans le buffer
		}

		enable_interrupts(GLOBAL);

		if (erreur)
			printf ("Erreur\n\r");
		else {
			commande = buffer[1] * 0x100 + buffer[0];
			printf ("%x %x Touche %d\n\r", buffer[1], buffer[0], buffer[0]);
			switch(commande) {
				case CODEIR_AV:
					mot_avancer();
					delay_ms(500);
					break;
				case CODEIR_AR:
					mot_reculer();
					delay_ms(500);
					break;
				case CODEIR_ST:
					mot_arreter();
					delay_ms(500);
					break;
				case CODEIR_RG:
					mot_rotation_gauche();
					delay_ms(500);
					break;
				case CODEIR_RD:
					mot_rotation_droite();
					delay_ms(500);
					break;
				case CODEIR_VG:
					mot_virage_gauche();
					delay_ms(500);
					break;
				case CODEIR_VD:
					mot_virage_droite();
					delay_ms(500);
					break;
				case CODEIR_ARG:
					mot_arriere_gauche();
					delay_ms(500);
					break;
				case CODEIR_ARD:
					mot_arriere_droite();
					delay_ms(500);
					break;
				case CODEIR_UP:
					vitesse_up();
					delay_ms(500);
					break;
				case CODEIR_DWN:
					vitesse_down();
					delay_ms(500);
					break;
				default:
					break;
			}
		}

		led_verte_off();
	}
}
