/*
	Nueva Rutina de manejo de LCD para HiTech


Libreria para manejo de LCD con protocolo de 4 bits
Funciones utilizables:
	InitLCD (puerto); el parametro puerto indica cual es el
puerto que se va a conectar al display.
	ReadLcd (); devuelve el caracter de la posicion actual
	WriteCharLcd (caracter); el parametro es el caracter a imprimir
	WriteStrLcd (cadena); el parametro es el texto a imprimir
	GotoxyLcd (x,y); lleva el cursor a las cordenadas indicadas
	ClearLcd (); borra la pantalla y pone el cursor en el inicio
	LcdOn (); enciende el display
	LcdOff (); apaga el display
	SetCursorLcd (On,Blink); Setea el estado del cursor 
On = 1: cursor encendido, On = 0: cursor apagado. 
Blink = 1: parpadea cursor, Blink = 0: no parpadea cursor

	Los bits utilizados son 0..3 Data hacia el display. 4 Enable,
5 Rs y 6 RW 

	Tambien exite una funcion WriteByteLcd (byte,dir) que se la
puede utilizar para distintas instrucciones hacia el display



*/


typedef struct {
					unsigned Data:4;
					unsigned En:1;
					unsigned RS:1;
					unsigned RW:1;
				}	pines;

pines * volatile LCDPort;	
unsigned char * volatile TrisLCD;

#include <string.h>



unsigned char ReadLcd ()
{
	unsigned char high, low;
	*TrisLCD = 0b10001111;
	(*LCDPort).RS = 0;
	(*LCDPort).RW = 1;
	(*LCDPort).En = 1;
	__delay_us (1);
	high = (*LCDPort).Data;
	(*LCDPort).En = 0;
	__delay_us (1);
	(*LCDPort).En = 1;
	low = (*LCDPort).Data;
	(*LCDPort).En = 0;
	*TrisLCD = 0b10000000;
	return ((high << 4) | low);
}

void WriteNibbleLcd (unsigned char data)
{
	(*LCDPort).Data = data;
	(*LCDPort).En = 1;
	__delay_us (2);
	(*LCDPort).En = 0;
}

void WriteByteLcd (unsigned char data, unsigned char dir)
{
	while ((ReadLcd(),7 == 1));
	(*LCDPort).RS = (bit)dir;
	(*LCDPort).RW = 0;
	WriteNibbleLcd (data>>4);
	WriteNibbleLcd (data &0xF);	
}

void WriteStrLcd (char *palabra)
{
	unsigned char cuenta;
	for	(cuenta = 0; cuenta < strlen(palabra); cuenta++)
	{
		WriteByteLcd (palabra[cuenta],1);
	}
}

void WriteCharLcd (char letra)
{
	WriteByteLcd (letra,1);
}

void GotoxyLcd (unsigned char x, unsigned char y)
{
	if (y == 1) y = 0;
	else
	  if (y == 2) y = 0x40;
	x--;
	WriteByteLcd (((y+x)|0x80),0);
}

void ClearLcd (void)
{
	WriteByteLcd (1,0);
}

void SetCursorLcd (unsigned char On, unsigned char Blink)
{
	unsigned char salida;
	salida = 0b11<<1;
	salida = (salida|(bit)On)<<1;
	salida = salida|(bit)Blink;
	WriteByteLcd (salida,0);
}

void LcdOn (void)
{
	WriteByteLcd (0x0E,0);
}

void LcdOff (void)
{
	WriteByteLcd (0x08,0);
}

void InitLcd (int	puerto)
{
	unsigned char	contador;
	TrisLCD  = (unsigned char *) (0x80 + puerto);
	*TrisLCD = 0b10000000;
	LCDPort = (pines *) puerto;
	(*LCDPort).Data = 0;
	(*LCDPort).En = 0;
	(*LCDPort).RS = 0;
	(*LCDPort).RW = 0;

	__delay_ms (15);
	for (contador = 1; contador <=3; contador++)
	{
		WriteNibbleLcd (3);
		__delay_ms (5);
	}
	WriteNibbleLcd (2);
	WriteByteLcd (0x28,0);
	WriteByteLcd (0xE,0);
	WriteByteLcd (0x6,0);	
}