//Prueba interfaz MiniZ


#include <avr/io.h>

#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>

#define Bus_Datos PORTC
#define Bus_Control PORTA

#define RS  PORTA5               
#define RW  PORTA6
#define E   PORTA7

#define LED1 PORTL7
#define LED2 PORTL5
#define LED3 PORTG1

//Comandos para situar el cursor en inicio de líneas.
#define DDRA_LINEA1 0x80    //1000 0000
#define DDRA_LINEA2 0xC0    //1100 0000
#define DDRA_LINEA3 0x94    //1001 0100
#define DDRA_LINEA4 0xD4    //1101 0100


void inicializar_puertos();
void reseteo();
void escribir_valor_decimal(unsigned char registro);

//Funciones para escribir en el LCD
void lcd_inicializar();
void lcd_escribir_c(char caracter);
void lcd_escribir(char *cadena);
void posicionar_cursor(unsigned char x, unsigned char y);
void lcd_comando(char comando);
char lcd_invertir_bits(char caracter);

//Variables


volatile unsigned char botones;

int main(void)
{
    inicializar_puertos();
    reseteo();
    lcd_inicializar();


    char linea1[]="Interfaz MiniZ";  //Poner en la Flash de programa las cadenas.
    char linea2[]="con Arduino MeGa";
    char linea14[]="www.jmnlab.com";
    char linea15[]="Ultima Pulsacion:";
    char linea16[]="Boton 1.        ";
    char linea17[]="Boton 2.        ";
    char linea18[]="Boton 3.        ";
    char linea19[]="Boton Derecho.  ";
    char linea20[]="Boton Izquierdo.";
    char linea21[]="Boton Subir.    ";
    char linea22[]="Boton Bajar.    ";
    char linea23[]="Mando A:";
    char linea24[]="Mando B:";

    unsigned char copia_ADCH;




    posicionar_cursor(1,4);  
    lcd_escribir(linea1);         
    posicionar_cursor(2,3);         
    lcd_escribir(linea2);
    posicionar_cursor(4,4);
    lcd_escribir(linea14);

    _delay_ms(3000);
    lcd_comando(0x01);
     posicionar_cursor(1,1);
    lcd_escribir(linea15);
     posicionar_cursor(3,1);
    lcd_escribir(linea23);
     posicionar_cursor(4,1);
    lcd_escribir(linea24);

    while(1)
    {

        switch(botones)
        {

        case 7:
            posicionar_cursor(2,1);
            lcd_escribir(linea19);
            break;

        case 6:
            posicionar_cursor(2,1);
            lcd_escribir(linea21);
            break;

        case 5:
            posicionar_cursor(2,1);
            lcd_escribir(linea22);
            break;

        case 4:
            posicionar_cursor(2,1);
            lcd_escribir(linea20);
            break;

        case 3:
            posicionar_cursor(2,1);
            lcd_escribir(linea18);
            PORTL |= (1<<LED2);
            PORTG &= ~(1<<LED3);
            PORTL &= ~(1<<LED1);
            break;

        case 2:
            posicionar_cursor(2,1);
            lcd_escribir(linea17);
            PORTG &= ~(1<<LED3);
            PORTL &= ~(1<<LED2);
            PORTL |= (1<<LED1);
            break;

        case 1:
            posicionar_cursor(2,1);
            lcd_escribir(linea16);
            PORTL &= ~(1<<LED1);
            PORTL &= ~(1<<LED2);
            PORTG |= (1<<LED3);
            break;

        default: break;
        }

        ADMUX  &= ~(1<<MUX0);             //Canal 0.
        _delay_us(600);                     
        copia_ADCH=ADCH;
         posicionar_cursor(3,10);
        escribir_valor_decimal(copia_ADCH);

         posicionar_cursor(4,10);        //Canal 1
        ADMUX  |= (1<<MUX0);    
        _delay_us(600);                     
        copia_ADCH=ADCH;
        escribir_valor_decimal(copia_ADCH);
    }
}

void inicializar_puertos()              //Configurar hardware del pic.
{
   //Configurar entradas y salidas.

   DDRC=0xFF;     //1111 1111
   PORTC=0x00;
      
   DDRA|=((1<<RS)|(1<<RW)|(1<<E));     //1110 0000
   PORTA &= ~(1<<E);  
    
   DDRL= 0xA0;      //1010 0000
   PORTL=0x00;

   DDRG =0x02;      //0000 0010
   PORTG=0x00;

   //Configurar interrupciones externas.

   PCICR |= (1<<PCINT2);
   PCMSK2 |= 0xFE;
   sei();

   //Configurar ADC

    ADMUX |=(1<<REFS0);                           //Tensión de referencia 5 voltios.
    ADMUX |=(1<<ADLAR);                           //8 bits de resolución.
                                                  //Canal ADC por defecto ADC0, no tenemos que cambiarlo.
    ADCSRA |=(1<<ADATE);                          //Habilitamos el Free Running Mode, por defecto seleccionado
    ADCSRA |=((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));  //Prescaler 128, Fadc 125 KHz @ 16MHz.
    DIDR0 |= ((1<<ADC0D)|(1<<ADC1D));             //Apagamos la parte digital del puerto.
    ADCSRA |= (1<<ADEN);                           //Encendemos ADC
    ADCSRA|= (1<<ADSC);                              //Comenzar conversiones.
}

void lcd_inicializar() //Se mandan los comandos de configuración según el dibujo.
{
    _delay_ms(100);
                       
    lcd_comando(0x3C);    //Function Set RS0 RW0 0011NF** 0011 1100
    lcd_comando(0x3C);    //Function Set
    lcd_comando(0x0C);    //Display ON/OFF Control RS0 RW0 00001DCB 0000 1100
    lcd_comando(0x01);    //Display Clear RS0 RW0 00000001
    lcd_comando(0x06);    //Entry Mode Set RS0 RW0 000001I/DS 0000 0110
}

void lcd_escribir_c(char caracter)
{
    Bus_Control |= (1<<RS);        //RS1    Dato
    Bus_Control &= ~(1<<RW);  //RS0
    Bus_Datos = lcd_invertir_bits(caracter);       
    Bus_Control |= (1<<E);
    _delay_us(100);
    Bus_Control &= ~(1<<E);
    _delay_ms(1);
}

void lcd_comando(char comando)
{
    Bus_Control &= ~(1<<RS);    //RS0   Comando
    Bus_Control &= ~(1<<RW);   //RW0
    Bus_Datos  = lcd_invertir_bits(comando);           //Comando
    Bus_Control |= (1<<E);
    _delay_us(100);
   Bus_Control &= ~(1<<E);
    _delay_ms(1);

}

void lcd_escribir(char *cadena)
{
    char *inicio = cadena;
    unsigned char i=0;

    for(i=0;((inicio[i]!='\0')&&(i<20));i++)
    {
        Bus_Control |= (1<<RS);    //RS0 RW0 caracter
        Bus_Control &= ~(1<<RW);
        Bus_Datos  = lcd_invertir_bits(inicio[i]);       
        Bus_Control |= (1<<E);
        _delay_us(100);
       Bus_Control &= ~(1<<E);
    _delay_ms(1);
    }
}

void posicionar_cursor(unsigned char x, unsigned char y) //línea x 1 a 4, carácter y de 1 a 20.
{                                                                                               
    unsigned char comando=DDRA_LINEA1;
    switch(x)
    {
        case 1:
        {
            comando=DDRA_LINEA1+y-1;
        }break;
        case 2:
        {
            comando=DDRA_LINEA2+y-1;
        }break;
        case 3:
        {
            comando=DDRA_LINEA3+y-1;
        }break;
        case 4:
        {
            comando=DDRA_LINEA4+y-1;
        }break;
        default:break;
    }
        lcd_comando(comando);
}

char lcd_invertir_bits(char caracter)
{
    char copia_caracter=caracter;
    char caracter_cambiado=0x00;

    caracter_cambiado |= (((copia_caracter)&(0x80))>>7);

    copia_caracter=caracter;
    caracter_cambiado |= (((copia_caracter)&(0x40))>>5);

    copia_caracter=caracter;
    caracter_cambiado |= (((copia_caracter)&(0x20))>>3);

    copia_caracter=caracter;
    caracter_cambiado |= (((copia_caracter)&(0x10))>>1);

    copia_caracter=caracter;
    caracter_cambiado |= (((copia_caracter)&(0x08))<<1);

    copia_caracter=caracter;
    caracter_cambiado |= (((copia_caracter)&(0x04))<<3);

    copia_caracter=caracter;
    caracter_cambiado |= (((copia_caracter)&(0x02))<<5);

    copia_caracter=caracter;
    caracter_cambiado |= (((copia_caracter)&(0x01))<<7);    
            
    return(caracter_cambiado);
}

void reseteo()
{

    PORTL |= ((1<<LED1)|(1<<LED2));
    PORTG |= (1<<LED3);
    _delay_ms(500);
    PORTL &= ~((1<<LED1)|(1<<LED2));
    PORTG &= ~(1<<LED3);
    _delay_ms(500);
    PORTL |= ((1<<LED1)|(1<<LED2));
    PORTG |= (1<<LED3);
    _delay_ms(500);
    PORTL &= ~((1<<LED1)|(1<<LED2));
    PORTG &= ~(1<<LED3);
    _delay_ms(500);
    PORTL |= ((1<<LED1)|(1<<LED2));
    PORTG |= (1<<LED3);
    _delay_ms(500);
    PORTL &= ~((1<<LED1)|(1<<LED2));
    PORTG &= ~(1<<LED3);
}

ISR(PCINT2_vect)
{

    if ((PINK&(1<<PINK1))==0)
        botones=7;

    else if ((PINK&(1<<PINK2))==0)
        botones=6;

    else if ((PINK&(1<<PINK3))==0)
        botones=5;

    else if ((PINK&(1<<PINK4))==0)
        botones=4;

    else if ((PINK&(1<<PINK5))==0)
        botones=3;

    else if ((PINK&(1<<PINK6))==0)
        botones=2;

    else if ((PINK&(1<<PINK7))==0)
        botones=1;

    PCIFR  |=(1<<PCIF2);
}

void escribir_valor_decimal(unsigned char registro) //Escribir binario a decimal.
{

    char centenas = 0;
    char decenas = 0;
    char unidades = 0;


    while(registro>=100)
    {
        registro= registro -100;
        centenas++;
    }
    while(registro>=10)
    {
        registro=registro -10;
        decenas++;
    }
    while(registro>0)
    {
        registro=registro-1;
        unidades++;
    }   
    lcd_escribir_c(centenas | 0b00110000);
    lcd_escribir_c(decenas | 0b00110000);
    lcd_escribir_c(unidades | 0b00110000);
}