// Cargar el valor de los pines neceasarios
#define VALOR_D7 PORTDbits.RD3
#define VALOR_D6 PORTDbits.RD2
#define VALOR_D5 PORTDbits.RD1
#define VALOR_D4 PORTDbits.RD0
#define VALOR_RS PORTEbits.RE0
#define VALOR_EN PORTEbits.RE1

//Condiguracion de los puertos.
#define PUERTO_D7 TRISDbits.TRISD3
#define PUERTO_D6 TRISDbits.TRISD2
#define PUERTO_D5 TRISDbits.TRISD1
#define PUERTO_D4 TRISDbits.TRISD0
#define PUERTO_E0 TRISEbits.TRISE0
#define PUERTO_E1 TRISEbits.TRISE1

//Instrucciones del LCD.
#define _lcd_display_clear 1
#define _lcd_return_home 2
#define _lcd_cursor_left 16
#define _lcd_cursor_right 20
#define _lcd_screen_left 24
#define _lcd_screen_right 28
#define _lcd_writeMoveleft_screenNotmove 4
#define _lcd_writeMoveleft_screenMove 5
#define _lcd_writeMoveright_screenNotmove 6
#define _lcd_writeMoveright_screenMove 7
#define _lcd_DisplayOn_CursorOff_BlinqOff 12
#define _lcd_DisplayOn_CursorOff_BlinqOn 13
#define _lcd_DisplayOn_CursorOn_BlinqOff 14
#define _lcd_DisplayOn_CursorOn_BlinqOn 15
#define _lcd_Bajar_linea 384

/////////////Arrays de valores de caracteres personalizados/////////////////////
unsigned char cara[8]= {0X00, 0X1B, 0X00, 0X04, 0X04,0X11, 0X0E, 0X00};
unsigned char corazon [8]= {0X00, 0x00, 0X1B, 0X15, 0X11, 0X0A, 0X04, 0X00};
unsigned char posicion_cursor =0;
////////////////////////////////////
void config_puertos (void)
{ //Todo puertos de salida.
    //Salidas de datos
    PUERTO_D7 = 0;
    VALOR_D7 = 0;
    PUERTO_D6 = 0;
    VALOR_D6 = 0;
    PUERTO_D5 = 0;
    VALOR_D5 = 0;
    PUERTO_D4 = 0;
    VALOR_D4 = 0;
    //Salidas de control.
    PUERTO_E1 = 0;
    VALOR_EN = 0;
    ANSELbits.ANS6 = 0; //Salida digital
    PUERTO_E0 = 0;
    VALOR_RS = 0;
    ANSELbits.ANS5 = 0; //Salida digital
}

void lcd_ini4bits (void)
{
    __delay_ms (16); //Espero mas de 15 ms para iniciar el LCD
    lcd_comando(); //Coloco el pin RS a 0 para ponerlo en modo instruccion
    lcd_mando_comando(3);
    __delay_ms (5);
    lcd_mando_comando (3);
    __delay_us (1000);
    lcd_mando_comando (3);
    __delay_us (1500);
    /////////////////////////////////////////////
    lcd_mando_comando(2); //Funcion set, interface para 4 bits
    __delay_us(1500);
    lcd_mando_comando (2);
    __delay_us(1500);
    lcd_mando_comando (8); //Funcion set Nº lineas y tamaño de fuente.
    __delay_us(1500);
    lcd_mando_comando(0);
    __delay_us(1500);
    lcd_mando_comando (8); //Display off
    __delay_us(1500);
    lcd_mando_comando(0);
    __delay_us(1500);
    lcd_mando_comando(1); //Display clear
    __delay_us(1500);
    lcd_mando_comando(0);
    __delay_us(1500);
    lcd_mando_comando(6); //Funcion Set, cursor incrementa su posición a la derecha.
    __delay_us(1500);
    lcd_mando_comando(0); 
    __delay_us(1500);
    lcd_mando_comando(15); //Enciendo el display
    __delay_us(1500);
    return;
}

void lcd_mando_comando(unsigned char comando)
{
    VALOR_D7 = (comando >> 3);
    VALOR_D6 = (comando >> 2);
    VALOR_D5 = (comando >> 1);
    VALOR_D4 = (comando);
    lcd_enable();
    return;
}
void lcd_mando_instruccion (unsigned char instruccion)
{
    lcd_comando(); //RS = 0;
    __delay_us(1000);
    lcd_mando_comando ((instruccion >>4) & 0B00001111 ); //Primero los 4 bits mas significativos
    lcd_comando();
    __delay_us(1000);
    lcd_mando_comando (instruccion & 0B00001111);
                        if ((instruccion ==_lcd_display_clear ) || (instruccion ==_lcd_return_home ))
                            posicion_cursor = 0;
                        
    return;
}

void lcd_mando_letra (unsigned char letra)
{
    lcd_dato(); //RS = 1;
    __delay_us(1000);
    lcd_mando_comando ((letra >>4) & 0B00001111 ); //Primero los 4 bits mas significativos
    lcd_dato();
    __delay_us(1000);
    lcd_mando_comando (letra & 0B00001111);
    if (letra > 8)
    posicion_cursor ++;
    return;
}

void lcd_comando (void) // Se pondrá el pin 4 (RS) del Display que en mi caso sera del micro RE0
{
    VALOR_RS = 0;
    return;
} //RS = 0 para mandar comandos de instrucion al LCD

void lcd_dato (void)
{
    VALOR_RS = 1;
    return;
} //RS = 1 para mandar datos de escritura al LCD

void lcd_enable (void) // Hay que provocar un flanco de bajada para que el Display coja lo que le mandamos
{
    VALOR_EN = 1;
    __delay_us(1000); //10us para que le de tiempo a ponerse bien a 1 el bit.
    VALOR_EN = 0;
    return;
}

///////////Instrucciones para mover cursor y screen////////////////////


void lcd_setDDRAMadress_cursor (unsigned char x,unsigned char y)//Funcion para posicionar el cursor en (x,y)
{
    char localidad_memoria;
    switch (x)
    {
       case 1: localidad_memoria = (0x80 + (y-1)); break; //Fila 1 Columna Y (Se le resta 1 porque la )
       case 2: localidad_memoria = (0xC0 + (y-1)); break; //Fila 2 Columna Y (posicion inicial es 0 no 1)
    }
    lcd_mando_instruccion (localidad_memoria);
    return;
}

void lcd_w_letra_position (unsigned char x, unsigned char y, unsigned char letra)
{
    lcd_setDDRAMadress_cursor(x,y);
    lcd_mando_letra (letra);
    return;
}

void lcd_w_string (unsigned char *texto)
{
    while (*texto)
    {
        if(posicion_cursor == 16)
            lcd_setDDRAMadress_cursor (2,1);
        if (posicion_cursor == 32)
        {
            posicion_cursor = 0;
            __delay_ms (4000);
            lcd_mando_instruccion (_lcd_display_clear);
        }
        
        lcd_mando_letra(*texto);
        texto ++; 
    }
    
    return;
}

void lcd_w_string_position(unsigned char x, unsigned char y, unsigned char *texto)
{
    lcd_setDDRAMadress_cursor (x, y);
    while (*texto)
    {
        lcd_mando_letra(*texto);
        texto ++;
    }
    return;
}

void crear_caracter ( unsigned char posicion,char emoji[8])
{//Primera posicion 0X40 hasta la 47, así hasta rellenar los 8 caracteres posibles a crear
    //Se crean todos los caracteres que se necesiten y luego ya se imprimen.
    //Luego a la hora de imprimir caracter se imprimiran desde la posición 0x00 hasta la 0x07.
    //Por lo que habrá que usar la funcion lcd_mando_letra (0X00) a la (0x07)
    unsigned char i;
    lcd_mando_instruccion(posicion);
    for(i=0; i<8; i++)
    lcd_mando_letra(emoji[i]);
    lcd_setDDRAMadress_cursor(1,1);
    //lcd_mando_instruccion(_lcd_cursor_right);
    return;
    /* crear_caracter(0X48,corazon); Ejemplo ya del main 
     lcd_mando_letra(0X01);
     lcd_mando_letra(0X01); Se escribirian 3 corazones
     lcd_mando_letra(0X01);*/
}
