/*****************************************************
Chip type               : ATmega328P
Program type            : Application
AVR Core Clock frequency: 16,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/

#include <mega328p.h>
#include <delay.h>
#define ADC_VREF_TYPE 0x60

// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}

char c=0; char d;char i,j,k,l;char v,u,w=1,m,n,o,p,x,y,z=0;signed char q1,r1,s1,t1;
signed char q,r,s,t; char e,f,g,h,a,b;char start=0,alarm=0,al=0,st,z1=0,light,ala=0;
eeprom char eep0=0,eep1=0,eep2=0,eep3=0;

// Pin change 0-7 interrupt service routine
interrupt [PC_INT0] void pin_change_isr0(void)
{
if(PINB.4==0)w++;     //переключение часов,будильника,таймера, кнопка time alarm
if(w==6)w=1;

if(PINB.0==0&&w==1)ala++;
}

// Pin change 8-14 interrupt service routine
interrupt [PC_INT1] void pin_change_isr1(void)
{
  if((PINC.4==0)&&(w==4)){s1++;}
  if((PINC.4==0)&&(w==3)){s++;}
  if((PINC.4==0)&&(w==2)){o++;}
  if((PINC.4==0)&&(w==1)){k++;}

  if((PINC.5==0)&&(w==4)){q1++;}   //кнопки настройки минут и часов
  if((PINC.5==0)&&(w==3)){q++;}
  if((PINC.5==0)&&(w==2)){m++;}
  if((PINC.5==0)&&(w==1)){i++;}
}
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
        PORTC=0x0F;                             // гасим все разряды
        if(c==0){PORTC.0=0;d=i;u=m;x=q;b=e;st=q1;}     //единицы минут
        if(c==1){PORTC.1=0;d=j;u=n;x=r;b=f;st=r1;}     // десятки минут поочередное включение разрядов 83 Гц прерывания
        if(c==2){PORTC.2=0;d=k;u=o;x=s;b=g;st=s1;}     // единицы часов
        if(c==3){PORTC.3=0;d=l;u=p;x=t;b=h;st=t1;}     //десятки часов
        c++;
        if(c==4)c=0;
}

// Timer1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
  if(start==1){v++;}
  if(v==60){i++;v=0;}
  if(i==10){j++;i=0;}
  if((j==6)&&(i==0)){k++;i=0;j=0;}    // счет секунд в единицы минут
  if(k==10){l++;k=0;}
  if((l==2)&&(k==4)){l=0;k=0;}
                                         // прерывание 1 Гц
  if(z==1){y++;}
  if(y==60){q--;y=0;}
  if(q==-1){q=9;r--;}                     //обратный отсчет поминутного таймера
  if((r==-1)&&(q==9)){s--;r=5;}
  if((s==-1)&&(r==5)&&(q==9)){t--;r=5;s=3;}
  if((q==9)&&(r==5)&&(s==3)&&(t==-1)){q=9;r=5;s=3;t=2;}

  if(z1==1){q1--;}
  if(q1==-1){q1=9;r1--;}             //обратный отсчет посекундного таймера
  if((r1==-1)&&(q1==9)){s1--;r1=5;}
  if((s1==-1)&&(r1==5)&&(q1==9)){t1--;r1=5;s1=9;}
  if((q1==9)&&(r1==5)&&(s1==9)&&(t1==-1)){q1=9;r1=5;s1=9;t1=5;}
}

// Timer2 output compare interrupt service routine // прерывание 100 Гц
interrupt [TIM2_COMPA] void timer2_compa_isr(void)
{
if((PINB.0==0)&&(w==2)){eep0=m;eep1=n;eep2=o;eep3=p;} //запись значения будильника в еепром

if(w==3){PORTB.2=1;} //светодиод индикации режима таймера
else
{
PORTB.2=0;
}
if(w==2)PORTB.3=1; //светодиод индикации режима будильника
else
{
PORTB.3=0;
}
if(w==4){PORTB.2=1;PORTB.3=1;} //индикация четвертого режима,секундный таймер/
}


static flash char digit[]={2,158,36,12,152,72,64,30,0,8,56,98};  //массив с цифрами
//static flash char digsec[]={3,159,37,13,153,73,65,31,1,9,57,99}; //массив цифр с точкой

void sec (char se)    //секундный таймер
{
PORTD=digit[se]|PORTD.0<<0;
}
void temp (char te)   //функция индикации температуры
{
PORTD=digit[te]|PORTD.0<<0;
}
void bud (char cifra) //функция индикации будильника
{
PORTD=digit[cifra]|PORTD.0<<0;
}
void ind (char chislo) //функция индикации часов
{
PORTD=digit[chislo]|PORTD.0<<0;
}
void timer (char tim) //функция индикации таймера
{
PORTD=digit[tim]|PORTD.0<<0;
}

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=Out Func2=Out Func1=Out Func0=In
// State7=T State6=T State5=0 State4=P State3=0 State2=0 State1=0 State0=P
PORTB=0x11;
DDRB=0x2E;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out
// State6=T State5=P State4=P State3=0 State2=0 State1=0 State0=0
PORTC=0x30;
DDRC=0x0F;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=In
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=P
PORTD=0x00;
DDRD=0xFF;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x02;
TCCR0B=0x04;
TCNT0=0x00;
OCR0A=0xB7;   // динамическая индикация 83 Гц
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: CTC top=OCR1A
// OC1A output: Toggle
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x40;
TCCR1B=0x0C;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0xF4;
OCR1AL=0x23;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: CTC top=OCR2A
// OC2A output: Toggle on compare match
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x02;
TCCR2B=0x07;
TCNT2=0x00;
OCR2A=0x9B;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: On
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x03;
PCMSK0=0x11;
PCMSK1=0x30;
PCIFR=0x03;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x02;

// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x02;

// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x02;

// USART initialization
// USART disabled
UCSR0B=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR1=0x00;

// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: Free Running
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
// ADC4: On, ADC5: On
DIDR0=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0xA7;
ADCSRB&=0xF8;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// TWI disabled
TWCR=0x00;

// Global enable interrupts
#asm("sei")

m=eep0;n=eep1;o=eep2;p=eep3;
ind(8);         // проверка всех сегментов
delay_ms(1000);
start=1;

while(1)
{

while(w==1)
{
 ind(d);

  if(i==10){j++;i=0;}
  if((j>=6)&&(i>=0)){i=0;j=0;}

  if(k==10){l++;k=0;}
  if((l>=2)&&(k>=4)){l=0;k=0;}

if((t==0)&&(s==0)&&(r==0)&&(q==0)&&(z==1))
{z=0;timer(0);while(PINB.4==1){al=(PINB.1^1);PORTB.5=al;}PORTB.5=0;} //сработка таймера в режиме часов(а нужно ли?)

if((t1==0)&&(s1==0)&&(r1==0)&&(q1==0)&&(z1==1))
{z1=0;sec(0);while(PINB.4==1){al=(PINB.1^1);PORTB.5=al;}PORTB.5=0;} //сработал таймер и горят нули пока не нажмешь кнопку time alarm

if((l==0)&&(k>=1))PORTC.3=1;  //гашение незначащего нуля в часах

if((l==eep3)&&(k==eep2)&&(j==eep1)&&(i==eep0)&&(ala==0)) // такой будильник
{
alarm=(PINB.1^1);PORTB.5=alarm;//чтобы буззер будильника прерывисто пищал
}
else
{
PORTB.5=0;
}
if(ala>=2)ala=0;
if(ala==0)PORTD.0=1;
if(ala==1)PORTD.0=0;

//read_adc(7);
//light=ADCH;
//if(light>1&&light<200){} //резерв//
}

while(w==2)
{
 bud(u);

  if(m==10){n++;m=0;}
  if((n>=6)&&(m>=0)){m=0;n=0;}

  if(o==10){p++;o=0;}
  if((p>=2)&&(o>=4)){p=0;o=0;}

if((p==0)&&(o>=1))PORTC.3=1; //гашение нуля и в будильнике
}

while(w==3)
{
 timer(x);

  if(q==10){r++;q=0;}
  if((r>=6)&&(q>=0)){q=0;r=0;}

  if(s==10){t++;s=0;}
  if((t>=2)&&(s>=4)){t=0;s=0;}

if((PINB.0==0)&&(w==3))z=1;  //запуск таймера
if((t==0)&&(s==0)&&(r==0)&&(q==0)&&(z==1)) // звонок таймера при обнулении
{
z=0;
timer(0);
while(PINB.4==1){al=(PINB.1^1);PORTB.5=al;}PORTB.5=0; //сработал таймер и горят нули
}                                           //пока не нажмешь кнопку time alarm
}

while(w==4)
{
   sec(st);

  if(q1==10){r1++;q1=0;}
  if((r1>=6)&&(q1>=0)){q1=0;r1=0;}

  if(s1==10){t1++;s1=0;}
  if((t1>=6)&&(s1>=0)){t1=0;s1=0;}

if((PINB.0==0)&&(w==4))z1=1; //запуск таймера
if((t1==0)&&(s1==0)&&(r1==0)&&(q1==0)&&(z1==1)) // звонок таймера при обнулении
{
z1=0;
sec(0);
while(PINB.4==1){al=(PINB.1^1);PORTB.5=al;}PORTB.5=0; //сработал таймер и горят нули пока не нажмешь кнопку time alarm
}
}

while(w==5)
 {
  temp(b);

  f=10;e=11;
  read_adc(6);
  a=(ADCH*0.389); // показатель преобразования из АЦП до 99
  g=a%10;         // а больше и не надо,0-100 градусов,(10-50)
  h=a/10;

  if((t==0)&&(s==0)&&(r==0)&&(q==0)&&(z==1))
{z=0;timer(0);while(PINB.4==1){al=(PINB.1^1);PORTB.5=al;}PORTB.5=0;} //сработка таймера в режиме часов(а нужно ли?)

if((t1==0)&&(s1==0)&&(r1==0)&&(q1==0)&&(z1==1))
{z1=0;sec(0);while(PINB.4==1){al=(PINB.1^1);PORTB.5=al;}PORTB.5=0;} //сработал таймер и горят нули пока не нажмешь кнопку time alarm
  }
}
}