#include <mega8.h>
#include <delay.h>
// I2C Bus functions
#asm
   .equ __i2c_port=0x15 ;PORTC
   .equ __sda_bit=4
   .equ __scl_bit=5
#endasm
#include <i2c.h>

// DS1307 Real Time Clock functions
#include <ds1307.h>

#include <1wire.h>
#include <ds18b20.h>
#asm  
  .equ __w1_port=0x18 ;PORTC
  .equ __w1_bit=7 
#endasm

// Declare your global variables here
unsigned char hh,mm,ss; //години, хвилини, секунди
unsigned char dday,day,month,year;   //день, місяць, рік

unsigned char seg,ls=0,outt=0;
char i=0;
unsigned int push=0, t=0, inf=0;     // змінна лічильник для мигання пунктів меню, змінна головного меню
unsigned char out=0;        // змінна, яка при мигані пункта визначає, буде він відображитись чи ні
unsigned char Numb[14] = {0x24,0xf6,0x1c,0x94,0xc6,0x85,0x5,0xF4,0x4,0x84,0xff,0x20,0x2d,0xcc}; //цифри семисегментника
unsigned char Out_s[7], dil;
unsigned char devices; // пристрої
int temp; //Температура
char znak=0;

void out_time(void)
{
      if (ss%2==0) PORTC.1=1; else PORTC.1=0; 
      if (inf!=0) PORTC.1=1;
      i++;  
      if (i==7) i=1;
      Out_s[1] = hh/10;
      Out_s[2] = hh%10;
      Out_s[3] = mm/10;
      Out_s[4] = mm%10;
      Out_s[5] = ss/10;
      Out_s[6] = ss%10;
      
      PORTB = seg;
      PORTD = Numb[Out_s[i]];   
      
      
      seg = seg - dil;
      dil *= 2;
      if (seg < 0x9F) {seg = 0xBE; dil = 1;} 
            
}

void out_date(void)
{
      PORTC.1 = 1; 
      i++;   
      if (i==7) i=1;
      Out_s[1] = day/10;
      Out_s[2] = day%10;
      Out_s[3] = month/10;
      Out_s[4] = month%10;
      Out_s[5] = year/10;
      Out_s[6] = year%10;
      
      PORTB = seg;
      PORTD = Numb[Out_s[i]];   
      
      seg = seg - dil;
      dil *= 2;
      if (seg < 0x9F) {seg = 0xBE; dil = 1;} 
            
}

void ch_time(void)
{
      t++;     
      if (push>0) push++;
      if (push>250) push=0;  
      
      out_time();
      if ( ( ( (inf==1)&&((i==1)||(i==2)) )||
      ( (inf==2)&&((i==3)||(i==4)) )||
      ( (inf==3)&&((i==5)||(i==6)) ) ) && out) PORTD = 0xFF;
      if (t>=200) {out=~out; t=0;}  
      
      if ((PINC.2==0)&&(inf==1)&&(push==0)){  //"+"
        hh++;
        if (hh==24) hh=0;
        rtc_set_time(hh,mm,ss);   
        push++;
      }
      
      if ((PINC.2==0)&&(inf==2)&&(push==0)){  //"+"
        mm++;
        if (mm==60) mm=0;
        rtc_set_time(hh,mm,ss);
        push++;
      }
      
      if ((PINC.2==0)&&(inf==3)&&(push==0)){  //"+"
        ss++;
        if (ss==60) ss=0;
        rtc_set_time(hh,mm,ss);
        push++;
      }   
      
      if ((PINC.3==0)&&(inf==1)&&(push==0)){  //"-"
        hh--;
        if (hh==0) hh=23;
        rtc_set_time(hh,mm,ss);
        push++;
      }
      
      if ((PINC.3==0)&&(inf==2)&&(push==0)){  //"-"
        mm--;
        if (mm==0) mm=59;
        rtc_set_time(hh,mm,ss);
        push++;
      }
      
      if ((PINC.3==0)&&(inf==3)&&(push==0)){  //"-"
        ss--;
        if (ss==0) ss=59;
        rtc_set_time(hh,mm,ss);
        push++;
      }
}

void ch_date(void)
{
      t++;         
      if (push>0) push++;
      if (push>250) push=0; 
      
      out_date();
      if ( ( ( (inf==4)&&((i==1)||(i==2)) )||
      ( (inf==5)&&((i==3)||(i==4)) )||
      ( (inf==6)&&((i==5)||(i==6)) ) ) && out) PORTD = 0xFF;
      if (t>=200) {out=~out; t=0;}  
      
      if ((PINC.2==0)&&(inf==4)&&(push==0)){  //"+"
        day++;
        if (day==32) day=1;
        rtc_set_date(dday,day,month,year);
        push++;
      }
      
      if ((PINC.2==0)&&(inf==5)&&(push==0)){  //"+"
        month++;
        if (month==13) month=1;
        rtc_set_date(dday,day,month,year);   
        push++;
      }
      
      if ((PINC.2==0)&&(inf==6)&&(push==0)){  //"+"
        year++;      
        if (year==100) year=0;
        rtc_set_date(dday,day,month,year);
        push++;
      }   
      
      if ((PINC.3==0)&&(inf==4)&&(push==0)){  //"-"
        day--;
        if (day==0) day=1;
        rtc_set_date(dday,day,month,year);
        push++;
      }
      
      if ((PINC.3==0)&&(inf==5)&&(push==0)){  //"-"
        month--;
        if (month==0) month=12;
        rtc_set_date(dday,day,month,year);
        push++;
      }
      
      if ((PINC.3==0)&&(inf==6)&&(push==0)){  //"-"
        if (year!=0) year--;
        rtc_set_date(dday,day,month,year);
        delay_ms(250);
      } 
}

void out_temp(void)
{
    while(1)
        {
        if (devices!=0)
              {
              temp=ds18b20_temperature(0);  //читаем температуру
              znak=0;
                if (temp>1000){                          //если датчик выдаёт больше 1000
                     temp=4096-temp;                     //отнимаем от данных 4096
                     znak=1;                            //и ставим знак "минус"
                     } 
              
              PORTC.1 = 0; 
              i++;   
              if (i==7) i=1;
              Out_s[1] = 10;
              Out_s[2] = 10+znak;
              Out_s[3] = temp/10;
              Out_s[4] = temp%10;
              Out_s[5] = 12;
              Out_s[6] = 13;
              
              PORTB = seg;
              PORTD = Numb[Out_s[i]];   
              
              seg = seg - dil;
              dil *= 2;
              if (seg < 0x9F) {seg = 0xBE; dil = 1;} 
              
              }   
              
        if ((PINC.2==0)||(PINC.3==0)) {delay_ms(250); break;}
      
        }
}

void main(void)
{

// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTB=0xFF;
DDRB=0xFF;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x0F;
DDRC=0x0F;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTD=0x00;
DDRD=0xFF;

// I2C Bus initialization
i2c_init();

// DS1307 Real Time Clock initialization
// Square wave output on pin SQW/OUT: Off
// SQW/OUT pin state: 0
rtc_init(0,0,0);

devices=w1_init();       
temp = 0;

seg = 0xBE;
dil = 1;
while (1)
      {
      // Place your code here

//      if (i==10) i=1;
//      if (i==0) i=9;
//      Out_s[1] = i;
//      
//      PORTB = seg;
//      PORTD = Numb[Out_s[1]];
//      if (PINC.2==0){  //"+"
//        i++;
//        delay_ms(250);
//      } 
//      if (PINC.3==0){  //"-"
//        i--;
//        delay_ms(250);
//      } 
      rtc_get_time(&hh,&mm,&ss);      
      rtc_get_date(&dday,&day,&month,&year); 
      if ((year<10)||(day>32)||(month>13)) {dday=1; day=1; month=1; year=10; rtc_set_date(dday,day,month,year);}
//      if ((hh>24)||(mm>60)||(ss>60)) {hh=0; mm=0; ss=0; rtc_set_time(hh,mm,ss);}  
      
      if ((ss==0x00)&&(mm==0x00)) PORTB.6 = 1; else PORTB.6 = 0;        
      
      
      if (PINC.0==0)  //якщо натиснули на PC1 та inf не рівний нулю, переходимо до повного режиму редагування  
        {                                                                                   
            inf++;     
            if (inf==7) inf=0;
            delay_ms(250);            
        }   

      if (((PINC.2==0)||(PINC.3==0))&&(inf==0))
        {
        out_temp();
        }             
        
      if (ls==0) ls = (ss+10)%60;
      if (ls==ss)
        if (outt) {outt=~outt; ls = (ss+3)%60;} else {outt=~outt; ls = (ss+10)%60;} 
      
         
      switch (inf)    //в залежності від inf вибирається функція, яка буде редагувати той чи інший елемент (всі функції описані в коді програми)
        {
        case 0: {
            if (outt) out_time(); else out_date();
            break;}//функція звичайного виведення часу
        case 1: {ch_time(); break;} //функція редагування поточного дня
        case 2: {ch_time(); break;} //функція редагування поточного дня
        case 3: {ch_time(); break;} //функція редагування поточного дня
        case 4: {ch_date(); break;} //функція редагування поточного часу
        case 5: {ch_date(); break;} //функція редагування поточного часу
        case 6: {ch_date(); break;} //функція редагування поточного часу
        } 
      
      }
}
