////////////////////////////////////////////////////////////////
//                DCF BigClock
//             Topor Zoltán - 2007. márc.
//            http://www.hobbielektronika.hu/
////////////////////////////////////////////////////////////////
#include <16F876A.h>
#include <STDLIB.H>


#FUSES NOWDT, HS, NOPUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD
#use delay(clock=20000000)
//#use rs232(baud=500,parity=N,rcv=PIN_A0,bits=8,stream=radio)

#define DAL_SCL   PIN_B4
#define DAL_SDA   PIN_B5

#define CAP_PIN   PIN_A0

#use i2c(master,sda=DAL_SDA, scl=DAL_SCL, FORCE_HW)

#define XTAL_FREQUENCY  20000000
#define TIMER1_FREQUENCY (XTAL_FREQUENCY / 4)      // 20000000/4

#define SZD   "%02u"
#define SZDH  "%2u"

#define DECODE_DATE

int16 TickCount   = 0;
int32 Ticker;
boolean NeedMeasureTemp = true;
signed int temp_h;
int temp_l;

int act_disp_counter = 0;
int act_disp = 0;
int temp_count = 0;
boolean volt_mar_dcf = false;

#include <display.c>
#include <m_dcf77.c>
//#include <m_manchester.c>
#include <m_DS1621M.C>

//===========================================================================
void chtime() {
//===========================================================================
   time.sec++;
   act_disp_counter++;
   if(act_disp_counter == 3) {
      act_disp++;
      if(act_disp == 3) {
         act_disp = 0;
         temp_count++;
         if(temp_count == 3) temp_count = 0;
      }
      act_disp_counter = 0;
   }
   if(time.sec == 60) {
      time.sec = 0;
      time.minute++;
      if(time.minute == 60) {
         time.minute = 0;
         time.hour++;
         if(time.hour == 24) {
            time.hour = 0;
            // dátum
            time.day++;
            switch (time.month) {
            case 1 : if(time.day==32)  { time.month++; time.day = 1; break; }  
            case 2 : if(time.year % 4 == 0) {
               if(time.day==30)  { time.month++; time.day = 1; break; } else
               { if(time.day==30)  { time.month++; time.day = 1; break; }
               }
            }
            case 3 : if(time.day==32)  { time.month++; time.day = 1; break; }
            case 4 : if(time.day==31)  { time.month++; time.day = 1; break; }
            case 5 : if(time.day==32)  { time.month++; time.day = 1; break; }
            case 6 : if(time.day==31)  { time.month++; time.day = 1; break; }
            case 7 : if(time.day==32)  { time.month++; time.day = 1; break; }
            case 8 : if(time.day==32)  { time.month++; time.day = 1; break; }
            case 9 :  if(time.day==31) { time.month++; time.day = 1; break; }
            case 10 : if(time.day==32) { time.month++; time.day = 1; break; }
            case 11 : if(time.day==31) { time.month++; time.day = 1; break; }
            case 12 : if(time.day==32) { time.month = 1; time.year++; time.day = 1; break; }
            }
            
         }
      }
   }
}


//===========================================================================
void Initialize_RTC(void) {
//===========================================================================
  Ticker = TIMER1_FREQUENCY;
  setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 );
  enable_interrupts( INT_TIMER1 );
} 

//===========================================================================
#int_RTCC
void RTCC_isr() {
//===========================================================================
RedrawDisplay();
}

//===========================================================================
#int_TIMER1                               
void TIMER1_isr()                         
//===========================================================================
{
  Ticker -= 65535;
  if ( Ticker < 65536 ) {
     Ticker += TIMER1_FREQUENCY;
     chtime();
  }
} 

//===========================================================================
#int_timer2
void isr_timer2(void) {
//===========================================================================
   TickCount++;
   if(TickCount==150) {
      dcf77_get_input();
   }
}

//======================================================================
#int_EXT
void EXT_isr() {
//======================================================================
   dcf77_isr();
}

//======================================================================
void init() {
//======================================================================
   input(PIN_B0);

   ext_int_edge(L_TO_H);

   init_temp(0);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);
   setup_timer_2(T2_DIV_BY_4,78,16);
   Initialize_RTC();
   enable_interrupts(INT_TIMER2);
   enable_interrupts(INT_RTCC); 
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);

   TickCount = 0;
   dcf_index = 0;

   time.hour = 0;
   time.minute = 0;
   time.sec = 0;
   time.year = 8;
   time.month = 1;
   time.day = 1;

   set_tris_c(0x00000000);
}

//======================================================================
void DisplayTime(){
//======================================================================
   display_putc("\f");
   printf(display_putc, SZD,time.hour);   
   display_putc(":");
   printf(display_putc,SZD,time.minute);   
   display_putc(":");
   printf(display_putc,SZD,time.sec);   
   if(!volt_mar_dcf) {
      if(input(PIN_B0)) display_putc(".");
   }
}

//======================================================================
void DisplayDate(){
//======================================================================
   display_putc("\f");
   printf(display_putc, SZD,time.year);   
   display_putc(".");
   printf(display_putc,SZD,time.month);   
   display_putc(".");
   printf(display_putc,SZD,time.day);   
   display_putc(".");
}


//======================================================================
void DisplayTemp(){
//======================================================================
   printf(display_putc,"\f%d",temp_h - 1 );  // ugyan nem megoldás, de szobában befűt magának
   if(bit_test(temp_l,7)) {
      display_putc(".5");
   } else {
      display_putc(".0");
   }
   display_putc(" °C");
}

//======================================================================
void main() {
//======================================================================
   init();
   for(;;) {
      if (dcf_time.HasNewTime) {
         dcf_time.HasNewTime = false;
         Ticker = TIMER1_FREQUENCY;
         time = dcf_time;
         time.sec = 1;//ez már csak az új perc elsőjénél fog beesni
         volt_mar_dcf = true;//többet nem nullázódik perckezdetnél
         NeedMeasureTemp = true;
      }

      if(NeedMeasureTemp && act_disp==2) {
                                       // vagyis most jönne az első hőmérséklet kiírás,
                                       // de előtte beolvassa a DS1621-et
         disable_interrupts(INT_RTCC); // kiírás interrupt leálítva
         output_low(SHIFT_RESET);      // shiftregiszter reset hogy ne legyen semmi a kijelzőn
         temp_h = read_high_temp(0);
         temp_l = read_low_temp(0);
         FlipBuffer();                 // ***
         ClearDisplay();               // alacsony pwm-nél villant egyet a kijelző
         FlipBuffer();                 // ***
         ClearDisplay();               // alacsony pwm-nél villant egyet a kijelző
         enable_interrupts(INT_RTCC);  // mstmár ki lehet írni a mért értéket
      }

      if(act_disp<2) {
         DisplayTime();
         NeedMeasureTemp = true;    // időkijelzés, azaz a következő hőmérsékletkijelzés előtt mérni kell
      } else {
         if(act_disp==2) {
            NeedMeasureTemp=false;
            if( temp_count == 2) {
               DisplayDate();
            } else {
               DisplayTemp();
            }
         }
      }      
      FlipBuffer();
      // delay_ms(10);

   }
}

