////////////////////////////////////////////////////////////////////////////////////////////////////
// JUAN NAVARRO ///////////////////////////////////////////////////////////////////////////////
// ENERO DE 2013 ///////////////////////////////////////////////////////////////////////////////
// BUENO AIRES - ARGENTINA /////////////////////////////////////////////////////////////////
// MANEJO DE PANTALLA LCD A 4BITS Y 8BITS ///////////////////////////////////////////////
// NIBBLE ALTO Y BAJO CON ///////////////////////////////////////////////////////////////////
//CONTROLADOR HD44780 O COMPATIBLE ///////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "milcd16-LCD.h"
//--------------------------------------------------------------------------------------------------
// Inicializacion LCD
void lcd_init(void)
{
    TRIS_E=0;   //configura como salida
    TRIS_RS=0;  //configura como salida

    PO_E=0;     //pone cero en E
    PO_RS=0;    //pone cero en RS

#ifdef BIT4

#ifdef LOWER
         TRIS_DATA_PORT&=0XF0; //configura parte baja del puerto como salida
#endif
#endif

//espera a que tension de fuente se estabilice
        delay_ms(45);
//.............................................................................
//procedimiento de reset para el lcd dado por el fabricante
//para mayor entendimiento ver dasheet de lcd
//Hitachi  HD44780
        lcd_nibble(0x30);
        delay_ms(5);
        lcd_nibble(0x30);
        delay_ms(1);
    	lcd_nibble(0x30);
        delay_ms(1);
//.............................................................................
#ifdef BIT4
		lcd_nibble(0x20);
   		delay_ms(1);
         lcd_write(LCD_FOUR_BIT & LCD_LINES_5X7, 0); //funsion set
#endif

        lcd_write(LCD_ON & LCD_CURSOR_OFF & LCD_BLINK_OFF,0); //display on off control
        lcd_write(LCD_CLEAR,0); //display clear
        lcd_write(LCD_ENTRY_CUR_RIGHT & LCD_ENTRY_STOP, 0); //entry mode set
        lcd_write(0x80,0);  //posiciono el cursor en la posicion 1 de la linea 1
        delay_ms(5);
}
//--------------------------------------------------------------------------------------------------
//esta funcion si el seteo esta a BIT4 siempre toma el nibble alto del DATO y lo ubica
//en el nibble alto o bajo del PORT de acuerdo al seteo de UPPER o LOWER
//si el seteo esta a BIT8 carga todo el dato al puerto
//recordar que primero se transmite la parte alta y despues la baja de los datos
 void lcd_nibble(unsigned char nibble)
{
#ifdef BIT4
                                                                                  //en nibble alto de port
#ifdef LOWER
      TRIS_DATA_PORT&=0XF0; //configura parte baja del puerto como salida
       DATA_PORT=((nibble>>4)&0x0F)|(DATA_PORT&0xF0); //cargo nibble alto de dato y lo pongo 
#endif                                                                                        //en nibble bajo de port
#endif

      delay_us(2);
	  PO_E=1;
	  delay_us(2);
	  PO_E=0;
}
//--------------------------------------------------------------------------------------------------
//esta funcion escribe el dato si rs=1 o escribe comando si rs=0 y lo hace a traves de la funcion
//lcd_nibble(); entonces si esta definido BIT4  carga el dato a la funcion lcd_nibble y esta trasmite
//como dijimos anteriormente la parte alta de dato colocandola en la parte alta o baja del puerto
//de acuerdo al seteo de UPPER o LOWER
//si estamos a BIT8 carga a lcd_nibble(); con los 8 bits de dato y esta hace el resto ya que en 
//la misma tambien esta seteado a BIT8
// esta es la descripcion de bits para leer y escribir en lcd
// RS=0 seleccina registro de datarucciones de lcd y puedo leer busy o escribir comandos
// RS=1 seleccina registro de datos de lcd y puedo leer datos de la DDRAM o escrir datos en ella
// RW=0 selcciono para escritura
// RW=1 selcciono para lectura
// convinacion de bits
// RS=0 RW=0 escribe comando
// RS=0 RW=1 lee comando (busy)
// RS=1 RW=0 escribe dato en ddram
// RS=1 RW=1 lee dato de ddram
void lcd_write(char data, char rs)
{
#ifdef BUSY
	while((lcd_read(0)==0x80)); // pregunta si lcd esta busy 
#else    
        delay_us(100);
#endif
	if (rs==0)
        PO_RS=0;
    else
        PO_RS=1;
        delay_us(40);   //tiempo que tarda en escribir el nibble
        lcd_nibble(data); //carga el dato y trasmite nibble alto
#ifdef BIT4
   		lcd_nibble(data<<4);// desplaza nibble bajo a alto y lo carga
#endif
}
//--------------------------------------------------------------------------------------------------
//funcion que realiza atraves de un puntero la escritura de una cadena de caracteres
//se escribe el string y fijarse que el puntero va a apuntar a la primer direccion del vector o cadena
//de caracteres, recordar que una cadena de caracteres termina siempre con un cero
void lcd_puts(const char * s)
{
	while(*s!=0) // mientras s sea distinto de cero sigue trasmitiendo
	lcd_write(*s++, 1); //escribe caracter e incrementa puntero, fijense que rs=1
}
//--------------------------------------------------------------------------------------------------
//funcion que direcciona la posicion de comienza de escritura
void lcd_gotoxy(char x, char y)
{
	if(y==0)
   		y = LCD_LINE1;
   	else
 	   	y = LCD_LINE2;
   	lcd_write(x+y, 0);
}
//--------------------------------------------------------------------------------------------------
void lcd_clear(void)
{
    lcd_write(LCD_CLEAR, 0);
}
//--------------------------------------------------------------------------------------------------
void lcd_gotoc(char x)	//accede a la posicion de escritura del lcd a traves del numero de caracter
{										// propiamente dicho
	lcd_write(x, 0);
}
//--------------------------------------------------------------------------------------------------
//colocar solo la direccion de escritura de cgram 0-8-16-24-32-40-48-56
//fijense (cgaddr | 0b01000000) que ya agrega el bit de direccion de la cgram
void lcd_putcgr(unsigned char cgaddr, const char*c)
{
    unsigned char i=0;
    lcd_write((cgaddr | 0b01000000),0 ); //rs=0 envia comando
        while(i<8)
        {
             lcd_write(*c++,1);
             i++;
        }
}
//--------------------------------------------------------------------------------------------------
//simplemente colocar la direccion donde fue alojado el caracter
//recordar que en la cgram podemos guardar solo 8 caracteres especiales con lo que sus
//direcciones de comienzo son 0 a 7
void lcd_putsymb(unsigned char symb)
{
    lcd_write(symb,1);
}
//--------------------------------------------------------------------------------------------------


