// lcd.h: funciones para manejo del LCD.                        //
//                                                              //
//    Conexiones de la placa:                                   //
//    RB0-7  -->  D0-7                                          //
//    RA0  -->  R/S                                             //
//    RA1  -->  R/W                                             //
//    RA2  -->  E
//
// IMPORTANTE:  Los interruptores de la placa RA0, RA1 y RA2
// deben estar a 1 para no cargar esa líneas y que el LCD funcione. //

#define RS PIN_A0
#define RW PIN_A1
#define E  PIN_A2

#byte port_b=6
/**********************************************************************
**         LCD_E
**  Produce un pulso de 1 microsegundo por la patita RA2 (E)
***********************************************************************/
void LCD_E()
{
    output_high(E);  // Activa E
    delay_us(1);
    output_low(E);   // Desactiva E
}
/**********************************************************************
**         LCD_BUSY
** Espera hasta que el LCD está libre. Para ello hay que leer el registro
** de instrucciones y mirar el bit 7 que es el BUSY flag.
***********************************************************************/

void LCD_BUSY()
{
    int8 data;
    set_tris_b(0xff);     // Puerto b en entrada
    output_low(RS);   // RS : instrucciones
    output_high(RW);  // R/W: leer
    do{
       delay_cycles(1);
       output_high(E);  // Activa senal E
       delay_us(1);        // Pequeno retardo
       data=input(PIN_B7);
       output_low(E);   // Desactiva senal E
    }while(data==1 );  // Si BUSY es 1 espero.
    set_tris_b(0);        // Puerto B salida.
    output_low(RW);   // R/W: escritura
}
/**********************************************************************
**         LCD_INSTR
** Esta función escribe una instrucción en el LCD.
***********************************************************************/

void LCD_INSTR(byte datoi)
{
    LCD_BUSY();         // Espero hasta que el LCD este libre
    output_low(RS);   // RS : instrucciones
    output_low(RW);   // R/W: escribir
    port_b = datoi;     // Cargo dato
    LCD_E();             // Pulso de enable
}

/**********************************************************************
**         LCD_DATO
** Esta función escribe un dato en la memoria DDRAM en la dirección a
** la que esté apuntando el AC. Según la zona que se esté visualizando
** en el LCD, se verá directamente o quedará escondida.
***********************************************************************/
void LCD_DATO(byte datod)
{
    LCD_BUSY();        // Espero hasta que el LCD este libre
    output_high(RS);  // RS : datos
    output_low(RW);   // R/W: escribir
    port_b = datod;     // Cargo dato
    LCD_E();             // Pulso de enable
}
/**********************************************************************
**         LCD_CADENA
** Esta función se apoya en LCD_DATO para escribir una cadena.
***********************************************************************/

void LCD_CADENA(char *p1)
{
    while ( *p1 != '\0')
    {
       LCD_DATO(*p1);
       p1++;
    }
}
/*********************************************************************
LCD_GOTOXY(x,y) Selecciona la nueva posicion de escritura en el display.
          X va de 1 a 40
          y == 1 : primera linea
          y == 2 : segunda linea
          (la esquina superior izquierda es 1,1)
*********************************************************************/
void LCD_GOTOXY( byte x, byte y)
{
   byte dir;

   if(y!=1)
     dir=0x40;  // Direccion de comienzo de segunda linea
   else
     dir=0;
   dir+=x-1;       // Calcula la direccion absoluta
   LCD_INSTR(0x80|dir); // Forma la instruccion completa
}

/**********************************************************************
**         LCD_INI
** Esta función inicializa el LCD siguiendo la secuencia que exige el
** fabricante.
***********************************************************************/

void LCD_INI()
{
    byte num;

    set_tris_b(0);       // RB salida
    set_tris_a(0x18);    // RA0-2  salidas
    output_low(RS);  // RS = 0
    output_low(E);  // E = 0

    for(num=3;num!=0;num--)
    {
       LCD_INSTR(0x38);   // modo 8 bits
       delay_ms(5);      // total 15 ms
    }
    LCD_INSTR(0x01);    // Borra LCD, Cursor a primera posicion e incremento.
    LCD_INSTR(0x0f);   // Cursor parpadeo, display on.
}

/**********************************************************************
**         PARPADEO
**  El LCD parpadea "veces" veces.
***********************************************************************/
void PARPADEO(byte veces)
{
    while ( veces != 0)
    {
       LCD_INSTR(0x0b);  //apago display
       delay_ms(500);
       LCD_INSTR(0x0f);  //enciendo display
       delay_ms(500);
       veces--;
    }
}
