#INCLUDE		<16F877.h>
#DEVICE ADC=8
#USE DELAY (clock=20000000)
#use FAST_IO(A)
#use FAST_IO(B)
#use I2C (MASTER,SDA=PIN_C4,SCL=PIN_C3,FORCE_HW)
#USE RS232 (BAUD=19200,XMIT=PIN_C6,RCV=PIN_C7,BITS=8)
#fuses HS,NOWDT,PUT,NOPROTECT,BROWNOUT,NOLVP,NOCPD,NOWRT
#bit RB7= 0x06.7
#bit RB6= 0x06.6
#bit RB5=0x06.5
#bit RB4=0x06.4
#bit RB3=0x06.3
#bit RB2=0x06.2
#bit RB1=0x06.1
#bit RA4=0x05.4
#bit RA5=0x05.5
#bit RA3=0x05.3

#INCLUDE "glcd.c"

/*******************************************************************************
  ESCRITURA EN EEPROM EXTERNA (A0=A1=0)
==========================================

   Recibe dos parámetros: ‘address’ (posición de la memoria EEPROM en la que se
      quiere escribir) y ‘data’ (byte que se va a escribir en la EEPROM).
   Siguiendo los pasos para una operación de escritura en una EEPROM 24FC1025:
           - Envía ‘address’ (byte alto y luego byte bajo).
           - Envía ‘dato’.
           - Espera para completar el ciclo interno de escritura en EEPROM.
   No devuelve ningún valor.

*******************************************************************************/
int x,y,z;
int1 control;
long int dir=0x0000;

void escr_eeprom(long int address, byte data)
{
	byte	high, low;		/* Bytes alto y bajo de la dirección EEPROM */
	i2c_start();		// Genera secuencia de START.
	i2c_write(0xa0);	// Envía byte de control para escribir.
	low=address;		// Separa la dirección EEPROM en dos bytes: el
	high=address>>8;	//   de mayor peso (high) y el de menor (low).
	i2c_write(high);	// Envía la dirección EEPROM; primero la parte
	I2c_write(low);		//   alta y luego la parte baja.
	i2c_write(data);	// Envía el dato a almacenar en la EEPROM.
	i2c_stop();			// Genera secuencia de STOP.
	delay_ms(10);		// Espera que el dato se almacene en EEPROM
}

/*******************************************************************************
  LECTURA DE EEPROM EXTERNA (A0=A1=0)
========================================

   Recibe el parámetros ‘address’ (posición de la EEPROM que se va a leer).
   Siguiendo los pasos para una operación de lectura en una EEPROM 24LC256:
           - Envía ‘address’ en la que “se va a escribir” (bytes alto-bajo).
           - Procede luego a leer el dato que hay en la dirección especificada.
   Devuelve el valor del dato leído.

*******************************************************************************/

byte lee_eeprom(long int address)
{
	byte	data;			/* Dato a leer de la EEPROM */
	byte	high, low; 		/* Bytes alto y bajo de la dirección EEPROM */

	i2c_start();		// Genera secuencia de START.
	i2c_write(0xa0);	// Envía byte de control para escribir.
	low=address;		// Separa la dirección EEPROM en dos bytes: el
	high=address>>8;	//   de mayor peso (high) y el de menor (low).
	i2c_write(high);	// Envía la dirección EEPROM; primero la parte
	I2c_write(low);		//   alta y luego la parte baja.
	i2c_start();		// Genera otra secuencia de START
	i2c_write(0xa1);	// Envía byte de control para leer.
	data=i2c_read(0);	// Lee el dato.
	i2c_stop();			// Genera una secuencia de STOP.
	return(data);		// Devuelve el dato leído.
}

/*******************************************************************************
	CREACION DE MENU
========================================

	Función que crea el menu
	Devuelve la seleccion.

*******************************************************************************/

int menu()
{
	char menu[5]={'M','e','n','u','\0'};
	char vis[]={'V','i','s','u','a','l','i','z','a','c','i','o','n','\0'};
	char conf[14]={'C','o','n','f','i','g','u','r','a','c','i','o','n','\0'};
	char env[14]={'E','n','v','i','o',' ','a',' ','P','C','\0'};
	int opc,opca;
	glcd_rect(0,0,127,11,YES,ON);				
	glcd_text57(10,2,menu,1,OFF);				//Escribe Menu
	glcd_text57(10,20,vis,1,ON);				//Escribe Visualizacion
	glcd_text57(10,30,conf,1,ON);				//Escribe Configuracion
	glcd_text57(10,40,env,1,ON);				//Escribe Envio a PC
	opc=opca=22;								//Inicializa el circulo de seleccion
	do
	{

		if(RB5==0)								//Si se pulsa abajo
		{
			if(opc==42)							//Si esta en el final del menu
				opc=22;							//Pasa al principio del menu
			else opc+=10;						//Si no pasa al siguiente
		}
		if(RB7==0)								//Si pulsa arriba
		{
			if(opc==22)							//Si esta en el inicio del menu
				opc=42;							//Pasa al final del menu
			else opc-=10;						//Si no pasa al siguiente
		}
		delay_ms(100);							//Espera para no producir rebotes de pulsador
		glcd_circle(4,opca,2,yes,OFF);			//Borra el circulo de seleccion
		glcd_circle(4,opc,2,yes,ON);			//Dibuja el circulo de seleccion
		opca=opc;
	}while(RB3!=0);								//Espera a seleccion
	delay_ms(100);
return opc;
}

/******************************************************************************
	MODO VISUAL
====================

	Subrutina que genera la visualizacion de rpms y aceleracion.

******************************************************************************/
void int visual()
{
	char xc[6],yc[6];
	//long int dir=0x0000,dnd;
	int xa,ya,c,ca;
	
	glcd_fillScreen(OFF);						//Borramos la pantalla
	glcd_rect(0,32,62,32,YES,ON);				//Dibuja de los ejes
	glcd_rect(32,0,32,64,YES,ON);
	x=0;										//Inicializa las varibles
	y=0;
	c=64;
	setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);		//Prepara el timer1 con el reloj interno y preescaler de 8
	enable_interrupts(INT_TIMER1);				//Habilita la interrupcion del timer1
	enable_interrupts(GLOBAL);					//Habilita las interrupciones globalmente
	set_timer1(3036);							//Carga para 100ms
	while(RB3!=0)
	{
		xa=x;
		ya=y;	
		while(control==0);						//esperamos a que salte la interrupcion
		set_timer1(3036);						//Carga para 100ms
		control=0;								//reinicializa la varible para la siguiente vuelta
		glcd_circle(xa,ya,1,NO,OFF);			//Borra la flecha anterior
		glcd_circle(x,y,1,NO,ON);				//Dibuja la nueva flecha	
		escr_eeprom(dir,x);
		dir++;
		escr_eeprom(dir,y);
		dir++;
		sprintf(xc,"x: %i",x);					//Transforma de entero a caracter la aceleracion en x
		sprintf(yc,"y: %i",y);					//Transforma de entero a caracter la aceleracion en x
		glcd_rect(70,15,120,40,YES,OFF);		//Borra los anteriores valores de la aceleracion
		glcd_text57(70,15,xc,1,ON);				//Escribe la aceleracion en x
		glcd_text57(70,30,yc,1,ON);				//Escribe la aceleracion en y
		ca=c;							
		glcd_rect(124,0,127,ca,YES,OFF); 		//Barra de rpms
		glcd_rect(124,64,127,c,YES,ON);
												//Manejo de la barra de rpms
		if(RB7==0)
			c--;
		if(RB5==0)
			c++;
	}
	disable_interrupts(INT_TIMER1);

	return;
}

/*******************************************************************************
	FUNCION PARA BORRAR LA MEMORIA DE LA EEPROM
==================================================

*******************************************************************************/

void borrar()
{
	long int i;
	char jc[15]={'D','a','t','o','s',' ','b','o','r','r','a','d','o','s','\0'};

	glcd_fillScreen(OFF);
	glcd_text57(10,40,jc,1,ON);
	dir=0x0000;
	while(RB3!=0);
}

void cal_eje()
{
	char cal[14]={'C','a','l','i','b','r','a','r',' ','e','j','e','s','\0'};
	glcd_fillScreen(OFF);
	glcd_rect(0,0,127,11,YES,ON);
	glcd_text57(10,2,cal,1,OFF);				//Escribe Calibrar rpm

	while(RB3!=0)
	{
	}
	return;
}
/******************************************************************************
	CALIBRACION DE RPMS
===========================

******************************************************************************/
void cal_rpm()
{
	char calrpm[13]={'C','a','l','i','b','r','a','r',' ','r','p','m','\0'};
	int barr=0;
	
	glcd_fillScreen(OFF);
	glcd_rect(0,0,127,11,YES,ON);
	glcd_text57(10,2,calrpm,1,OFF);				//Escribe Calibrar rpm
	while(RB3!=0)
	{
		glcd_rect(10,40,barr+10,50,YES,ON);	
		if(RB4==0)
			barr++;
		if(RB6==0)
			barr--;
		glcd_rect(barr+10,40,127,50,YES,OFF);
	}	
	return;
}
void conf()
{
	char conf[14]={'C','o','n','f','i','g','u','r','a','c','i','o','n','\0'};
	char borr[13]={'B','o','r','r','a','r',' ','d','a','t','o','s','\0'};
	char cal[14]={'C','a','l','i','b','r','a','r',' ','e','j','e','s','\0'};
	char calrpm[13]={'C','a','l','i','b','r','a','r',' ','r','p','m','\0'};
	int opc,opca;


	glcd_rect(0,0,127,11,YES,ON);
	glcd_text57(10,2,conf,1,OFF);				//Escribe Configuracion
	glcd_text57(10,20,borr,1,ON);				//Escribe Borrar datos
	glcd_text57(10,30,cal,1,ON);				//Escribe Calibracion de ejes
	glcd_text57(10,40,calrpm,1,ON);				//Escribe Tiempo de muestreo
	opc=opca=22;
	do
	{

		if(RB5==0)								//Si se pulsa abajo
		{
			if(opc==42)							//Si esta en el final del menu
				opc=22;							//Pasa al principio del menu
			else opc+=10;						//Si no pasa al siguiente
		}
		if(RB7==0)								//Si pulsa arriba
		{
			if(opc==22)							//Si esta en el inicio del menu
				opc=42;							//Pasa al final del menu
			else opc-=10;						//Si no pasa al siguiente
		}
		delay_ms(100);
		glcd_circle(4,opca,2,yes,OFF);			//Borra el circulo de seleccion
		glcd_circle(4,opc,2,yes,ON);			//Dibuja el circulo de seleccion
		opca=opc;								//Guarda la anterior posicion
	}while(RB3!=0);								//Espera a seleccion
	delay_ms(100);
	glcd_fillScreen(OFF);
	if(opc==22)
		borrar();
	if(opc==32)
		cal_eje();
	if(opc==42)
		cal_rpm();
	return;	
}


void env()
{
	long int dnd=0x0000;
	int xm,ym;
	char dat[]={'E','n','v','i','a','n','d','o',' ','d','a','t','o','s',' ','a',' ','P','C','\0'};
	printf(" Memoria\n");
	glcd_text57(5,25,dat,1,ON);
	printf("%lu",dir);
	while((RB3!=0)||(dnd<22))
	{
		xm=lee_eeprom(dnd);
		dnd++;
		ym=lee_eeprom(dnd);
		dnd++;
		printf("%lu",dnd);
		printf(" x:%i",x);						//Envia las aceleraciones al PC
		printf("/ y: %i\n\r",y);
	}
	printf(" Fin de Grabacion\n");
	printf(" Pulse seleccion\n");
	while(RB3!=0);
}
void main()
{
	int opc=0;

	port_b_pullups(PIN_B7);
	port_b_pullups(PIN_B6);
	port_b_pullups(PIN_B5);
	port_b_pullups(PIN_B4);
	port_b_pullups(PIN_B3);
	set_tris_d(0x00);
	set_tris_b(0b11111000);
	set_tris_a(0b00001111);
	output_a(0x00);
	glcd_init(ON);
	output_float(PIN_A0);
	output_float(PIN_A1);
	output_float(PIN_A2);
	output_float (PIN_C3);							// Dejamos flotantes los terminales
	output_float (PIN_C4);							//   asociados a la comunicación I2C.
	setup_adc_ports(AN0_AN1_AN2_AN3_AN4);
	setup_adc(ADC_CLOCK_INTERNAL);

while(true)
	{
	if(opc==22)
		visual();									//Entra en visualizacion
	if(opc==32)
		conf();										//Entra en configuracion
	if(opc==42)
		env();										//Entra en envio a PC
	glcd_fillScreen(OFF);							//Borra display para entrar en menu
	opc=menu();										//Entra en menu
	glcd_fillScreen(OFF);							//Borra display al salir del menu
	}
}

#INT_TIMER1
void conv()
{
	set_adc_channel(0);			
	x=read_adc();									//Captura la aceleracion en el eje x
	set_adc_channel(1);			
	y=read_adc();									//Captura la aceleracion en el eje y
	set_adc_channel(2);
	z=read_adc();									//Captura la aceleracion en el eje z
	x-=54;											//Trata la aceleracion para el display
	y-=65;
	control=1;
}
