#include <16f877a.h>
#use delay(clock=20000000)
#fuses HS,PUT,NOPROTECT,NOWDT,NOLVP
#byte portb=6
#byte portc=7
#byte portd=8
#include <flex_lcd.c>
#use standard_io(b,c)
//#use fast_io(b)

#define SEGUNDOS_EN_UNA_HORA 3600
#define SEGUNDOS_EN_UN_MINUTO 60


int32 Conta_Segundos=0,MomentoActual=0;
int32 Horas=0,Minutos=0,Segundos=0;
int set,flag_timer1;
byte last_b;

void Mi_Hora(void);
void Cambiar_Hora(int32 *Horas,int32 *Minutos);
void reset(void)
{
Conta_Segundos=0;
Momentoactual=0;
}

#INT_TIMER1
timer1_rsi()
{
set_timer1(32768);
++Conta_Segundos;
Mi_Hora();
lcd_gotoxy(6,1);
printf(lcd_putc,"%02ld:%02ld:%02ld    ",Horas,Minutos,Segundos);
}

// Interrupcion RB4 - RB7 /////////////////////////////////////////////////////
#INT_RB
rb_isr() 
{
    byte changes; 
    changes=last_b^portb;       //XOR.
    last_b=portb;
    if (bit_test(changes,5) && !bit_test(last_b,5))
    {                                                     
         lcd_gotoxy(6,2);
         lcd_putc("..              ");    //Indica que se va a incrementar las horas.
         delay_ms(200);
         lcd_gotoxy(6,2);
         lcd_putc("                ");
         delay_ms(200);
         lcd_gotoxy(6,2);
         lcd_putc("..              ");
         if(set==1)
         {
         lcd_gotoxy(1,2);
         lcd_putc("        ..      ");   // Indica que se van a incrementar los minutos
         delay_ms(250);
         lcd_gotoxy(1,2);
         lcd_putc("                ");
         delay_ms(250);
         lcd_gotoxy(1,2);
         lcd_putc("        ..      ");
         }
         set+=1;
         if (set==2)
         set=0;    
    }
    if (bit_test(changes,6) && !bit_test (last_b,6))   //INCREMENTAR.
    {
    Cambiar_hora(&Horas,&Minutos);
    }
    if (bit_test(changes,7) && !bit_test (last_b,7))   //DECREMENTAR.
    {
    Cambiar_hora(&Horas,&Minutos);       
    }
    Conta_Segundos=(Minutos*60)+(Horas*3600)+Segundos;
    bit_clear(portb,0);          //Solo modifico el nibble bajo sin tocar el alto 
    bit_clear(portb,1);          //y consigo escribir el port
    bit_clear(portb,2);
    bit_clear(portb,3);
    lcd_gotoxy(6,1);
    printf(lcd_putc,"%02ld:%02ld:%02ld    ",Horas,Minutos,Segundos);
    delay_ms(10);
    set_timer1(32768);   
}


// Programa Principal /////////////////////////////////////////////////////////
   
void  Mi_Hora()
      {
      MomentoActual=Conta_Segundos;
      Horas=MomentoActual/SEGUNDOS_EN_UNA_HORA; 
      MomentoActual%=SEGUNDOS_EN_UNA_HORA;               //Guarda el resto de la división entera. 
      Minutos=MomentoActual/SEGUNDOS_EN_UN_MINUTO;  
      MomentoActual%=SEGUNDOS_EN_UN_MINUTO;   
      Segundos=MomentoActual;
      if(Horas==24 && Minutos==0 && Segundos==0)
      {
      Horas=0;
      Minutos=0;
      Segundos=0;
      reset();
      }
      }
      
void Cambiar_hora(int32 *Horas,int32 *Minutos)
{
if(set==0)
   {
      if(portb==0b10110000)
      {
      ++*Minutos;
      if(*Minutos==60){*Minutos=0;}
      }
   }
if(set==1)
   {
      if(portb==0b10110000)
      {
      ++*Horas;
      if(*Horas==24){*Horas=0;}
      }
   }
if(set==0)
   {
      if(portb==0b01110000)
      {
      if(*Minutos==0){*Minutos=60;}
      --*Minutos;
      }
   }   
if(set==1)
   {
      if(portb==0b01110000)
      {
      if(*Horas==0){*Horas=24;}
      --*Horas;
      }
   }   
}      
       
void  main(void)
      {
      lcd_init();
      set_tris_b(0xf0);
      port_b_pullups(TRUE);
      portb=0xf0;
      setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT);//el preescaler q va es 2.
      enable_interrupts(INT_TIMER1);
      enable_interrupts(INT_RB);
      enable_interrupts(GLOBAL);
      set_tris_c(0b00000011);
      set_tris_d(0x00);
      lcd_gotoxy(1,1);
      lcd_putc("Reloj Digital");
      delay_ms(1500);
      lcd_putc("\fHora 00:00:00 ");
      lcd_gotoxy(1,2);
      lcd_putc("        ..      ");
      delay_ms(250);
      lcd_gotoxy(1,2);
      lcd_putc("                ");
      delay_ms(250);
      lcd_gotoxy(1,2);
      lcd_putc("        ..      ");
      delay_ms(250);
      set_timer1(32768);
         while(1)
         {
         
         }
       }
       
       
       
       
       
       


