#include <18F2550.h>
#device adc=10
#FUSES XT,NOWDT
#use delay(crystal=4000000)     // reloj a 4 MHz.

#use standard_io( A )
#use STANDARD_IO( B )

#define BUTTON_UP_PIN    PIN_C6    //PIN_A1
#define BUTTON_ENTER_PIN PIN_C7    //PIN_A2
#define BUTTON_EXIT_PIN  PIN_C7    //PIN_A2

#use i2c(Master,fast,sda=PIN_B0,scl=PIN_B1,force_sw,STREAM=DS3231_STREAM)
#include "DS3231.c"

#define DS18B20_PIN PIN_B6
#define PIN_DS18B20_DATA DS18B20_PIN
#include "ds18b20.c"

#define CPU_MHZ 4
#define delay_ms_break(t_ms,pinx)  for(int32 n=15.46*CPU_MHZ*t_ms ; !input(pinx) && n>0 ; n--)
#define lcd_set_cgram_char
//int     sensor;
float   temper;
signed  int16 value;

#include "LCD420_v2.C"

int horas=00,minutos=00,segundos=0,dia=0,mes=0,anio=00,dow=00;
signed int16 temperatura=0;
char grados=223;    //simbolo °
RTC_Time *reloj;

int16 voltaje_adc,corriente_adc;
float voltaje,corriente,potencia;

#define MENU_OPTION_COUNT 7
char* menuOptions[MENU_OPTION_COUNT]= {"Fecha-Hora-Tem.I/E","Fuente 5VDC/Regul.","Fuente 5VDC(FIJO)","Fuente 3,3V(FIJO)","Opcion 5","Opcion 6","Opcion 7"};

//=====================================================================

#define Ton  (100.*50)          // Tiempo de 50"
                                // Tiempo maximo 11minutos
                                // si hace falta mas se usa int32
#INT_TIMER2
void  TIMER2_isr(void)
{
    static int16 Tilum = Ton ;

    if(Tilum){
        if(!--Tilum)
            output_low(PIN_A5); // APAGA LCD
    }
    if (input(PIN_B7) == 1){
        output_high(PIN_A5);    // ENCIENDE LCD
        Tilum = Ton        ;    // Activa el display por 50"
    }                           // Resetea la cuenta si está encendido
}

//=====================================================================

void displayMenu(int8 select) {

    lcd_putc('\f');  // Limpiar la pantalla   
    lcd_gotoxy(2, 1); printf(lcd_putc, "Menu F.A. Opcion:");
               
    static int8 base=0;                                          
    
    if((select-base)>0x80)   base-- ;          // Para cuenta descendente
    else if((select-base)>2) base=select-2 ;

//    if((select-base)>0x80)   base=0 ;        // Para cuenta ascendente  
//    else if((select-base)>2) base++ ;
    
    for(int8 j=2,k=base ; j<5 ; j++,k++){
        lcd_gotoxy(1, j);
        if (select == k)
            printf(lcd_putc, "> %s", menuOptions[k]);
        else
            printf(lcd_putc, "  %s", menuOptions[k]); 
    }       
}

//=====================================================================

void reloj_lcd()
{
   lcd_gotoxy(2,2); printf(LCD_PUTC,"T.FA.:%Ld%cC",temperatura,grados);
   lcd_gotoxy(3,3); printf(LCD_PUTC,"%02u:%02u:%02u",horas,minutos,segundos);
   lcd_gotoxy(2,4); printf(LCD_PUTC,"%02u/%02u/20%02u",dia,mes,anio);
   lcd_gotoxy(1,2); printf(lcd_putc,"%c", 0);
    
}
//=====================================================================

void proc_Opcion1(){
        
    delay_ms(200) ;
    do{                 
        reloj= RTC_Get();
        horas = reloj->hours;
        minutos = reloj->minutes;
        segundos = reloj->seconds;
        dia = reloj->day;
        mes = reloj->month;
        anio = reloj->year;
        temperatura = Get_Temperature()/100;
         reloj_lcd();
         
        // ---------------------------------------------------
        ds18b20_read(&value) ;
        temper=value/16. ;

        lcd_gotoxy(14,3);
        printf(lcd_putc, "%.2f", temper); // temperatura exterior
        lcd_putc(223);                    // Imprimir el símbolo de grados Celsius (°)
        lcd_putc('C');     
        lcd_gotoxy(15,4); printf(lcd_putc, "T.EXT.");
       
        // ------------------------------------------------------------
        delay_ms_break(500,BUTTON_EXIT_PIN) ;
    } while(input(BUTTON_EXIT_PIN)==0);
}

void proc_Opcion2(){
    setup_adc_ports(AN0_TO_AN3);
    setup_adc(ADC_CLOCK_INTERNAL);

    do {
        set_adc_channel(0);
        delay_ms(100);
        voltaje_adc=READ_ADC();
        voltaje= 50.0 * voltaje_adc/1023.0;
        set_adc_channel(1);
        delay_ms(100);
        corriente_adc=READ_ADC();
        corriente= 5 * corriente_adc/1023.0;
        potencia= voltaje * corriente;
        lcd_gotoxy(2,2);
        printf(lcd_putc, " %02.2fV    %02.3fA ",voltaje,corriente);
        lcd_gotoxy(6,3);
        printf(lcd_putc, "P=%02.2fW  ",potencia);

        delay_ms_break(300,BUTTON_EXIT_PIN) ;
    } while(input(BUTTON_EXIT_PIN)==0);
   
    setup_adc_ports(NO_ANALOGS) ;         
}

void proc_Opcion3(){
    setup_adc_ports(AN0_TO_AN3);
    setup_adc(ADC_CLOCK_INTERNAL);

    do {
        set_adc_channel(2);
        delay_ms(100);
        voltaje_adc=READ_ADC();
        voltaje= 5.0 * voltaje_adc/1023.0;
        set_adc_channel(3);
        delay_ms(100);
        corriente_adc=READ_ADC();
        corriente= 5 * corriente_adc/1023.0;
        potencia= voltaje * corriente;
        lcd_gotoxy(2,2);
        printf(lcd_putc, " %02.2fV    %02.3fA ",voltaje,corriente);
        lcd_gotoxy(6,3);
        printf(lcd_putc, "P=%02.2fW  ",potencia);
 
        delay_ms_break(300,BUTTON_EXIT_PIN) ;
    } while(input(BUTTON_EXIT_PIN)==0);
    
    setup_adc_ports(NO_ANALOGS) ;

}
void proc_Opcion4(){

    lcd_gotoxy(6,2);
    printf(lcd_putc,"pruebas...");

    delay_ms(200) ;

    do {
        ds18b20_read(&value) ;
        temper=value/16. ;

        lcd_gotoxy(8,3);
        printf(lcd_putc, "%.2f", temper); // temperatura exterior
        lcd_putc(223);                    // Imprimir el símbolo de grados Celsius (°)
        lcd_putc('C');    
        lcd_gotoxy(1,3); printf(lcd_putc, "T.EXT.");
// ------------------------------------------------------------
        delay_ms_break(300,BUTTON_EXIT_PIN) ;
    } while(input(BUTTON_EXIT_PIN)==0);
    setup_adc_ports(NO_ANALOGS) ;
}

void proc_Opcion57(){

    lcd_gotoxy(6,2);
    printf(lcd_putc,"pruebas xx...");

    delay_ms(250) ;

    do {
// ------------------------------------------------------------
        delay_ms_break(300,BUTTON_EXIT_PIN) ;
    } while(input(BUTTON_EXIT_PIN)==0);
}

void main() {
 
   int BARRAT[8] = {0,10,10,0,17,14,0,0};
    ds18b20_read(&value) ;
    temper=value/16. ;

    lcd_init();
    lcd_set_cgram_char(0,BARRAT);
    lcd_putc('\f');      // Limpiar la pantalla inicialmente
    delay_ms(100);
  
    set_tris_c(0) ;

    setup_timer_2(T2_DIV_BY_16,125,5);   // 2.0 ms overflow, 10.0 ms interrupt
    enable_interrupts(INT_TIMER2);
    enable_interrupts(GLOBAL);

    displayMenu(0);

    c_time.hours  = 00 ;
    c_time.minutes= 54 ;
    c_time.seconds= 20 ;
    c_time.day    = 04 ;
    c_time.month  = 06 ;
    c_time.year   = 26 ;
    //RTC_Set(&c_time) ; // activar esta linea solo para poner en hora y fecha
                      // Luego desactivar para que no vuelva a cojer parametros
  
    while (TRUE) {
        static signed int selectedOption = 0 ;

        if (input(BUTTON_UP_PIN)) {

            selectedOption--;                                                    // Para cuenta descendente  
            if( selectedOption < 0)  selectedOption = MENU_OPTION_COUNT - 1;

//            selectedOption++;                                                  // Para cuenta ascendente  
//            if( selectedOption > (MENU_OPTION_COUNT - 1))  selectedOption = 0;

            displayMenu(selectedOption);
            delay_ms(250);     // AntiRebote
        }

        if (input(BUTTON_ENTER_PIN)) {
            lcd_putc('\f');
            lcd_gotoxy(1, 1);
            switch (selectedOption) {         
                case 0:
                    printf(lcd_putc,"Fecha/Hora/Temp.I/E");
                    proc_Opcion1() ;               
                    break;

                case 1:
                    printf(lcd_putc, "Selecc. 5v/Regul.");
                    proc_Opcion2() ;
                    break;

                case 2:
                    printf(lcd_putc, "Selecc. 5vdc/Amp.");
                    proc_Opcion3() ;
                    break;
                
                case 3:
                    printf(lcd_putc, "Selecc. 3,3Vdc/Amp.");
                    proc_Opcion4() ;
                    break;
            
               default:
                    printf(lcd_putc, "Opcion x seleccion");
                    proc_Opcion57() ;
            }
            displayMenu(selectedOption);
            delay_ms(500);     // AntiRebote
        }
    }
}
