#include <avr\io.h>
#include <avr\interrupt.h>
#include <avr\eeprom.h>
#include <util\delay.h>
#include <stdio.h>
// #define F_CPU 8000000UL  // 8 MHz

static unsigned char term_ac;
volatile static struct {unsigned a: 1;
		unsigned b: 1;
		unsigned c: 1;
		unsigned d: 1;
		unsigned e: 1;
		unsigned f: 1;
		unsigned g: 1;
		unsigned h: 1;
	   } tmp;

void EEPROM_write( unsigned int uiAddress, unsigned char ucData )
{	cli();
    while( EECR & ( 1 << EEPE ) );
    EEAR = uiAddress;
    EEDR = ucData;
    EECR |= ( 1 << EEMPE );
    EECR |= ( 1 << EEPE );
	sei();
}

unsigned char EEPROM_read( unsigned int uiAddress )
{	cli();
    while( EECR & ( 1<<EEPE ) );
    EEAR = uiAddress;
    EECR |= ( 1<<EERE );
	_delay_ms(10);
    return EEDR;
	sei();
}


int main(void)              // начало основой программы
 {
  unsigned int eeprom_log;
  volatile char  term_led;
  volatile unsigned char ac_up, ac_down, term_save, paus_u, paus_d, ed, des, term_real, term_desire, number, start, up, down;
  unsigned char seg[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x07,0x41,0x0C,0x21,0x0B,0xC7,}; //0-9 11=T,12=U,13=P,14=d,15=h,16=L
  
  
  DDRA   = 0xFF;	// все выводы, сконфигурировать как выходы
  DDRB   = 0xE4;	// Сконфигурировать 7,6,5 пины как выходы, а 4,3,2,1,0 как входы
  DDRD   = 0xFF;	// все выводы, сконфигурировать как выходы
  PORTB  = 0xFD;
  PORTD	 = 0xFF;
  tmp.a  = 0;
  tmp.b	 = 0;
  tmp.c	 = 0;
  tmp.d	 = 0;
  number = 0;
  up     = 0;
  down   = 0;
  start  = 0;
  TCCR1C = 0x00; // Определение
  TCCR1A = 0x00; // параметров
  TCCR1B = 0x04; // 16 битного счетчика Timer1
  TCCR0A = 0x00; // Определение параметров
  TCCR0B = 0x03; // 8 битного счетчика Timer0


  TIMSK  = 0x80;
  DIDR	 = 0x00;
  cbi(TIMSK, TOIE1); // Отключаем прерывание Timer1
  term_save   = EEPROM_read(0x0002);
  _delay_ms(100);
  eeprom_log  = EEPROM_read(0x0004);
  _delay_ms(100);
  term_desire = term_save;
  term_led    = 10;
  term_real	  = 17;
  term_ac	  = 11;
  des		  =  0;
  ed		  =  0;
  paus_u	  = 10;
  paus_d	  = 10;
  ac_up		  =  0;
  ac_down	  =  0;
  tmp.d		  =  1;
  sei();
  
  while (1)	// Бесконечный цикл
  {              
   	if (term_desire > 90) term_desire = 30;
	if ((~PINB)&(1 << 4)) up++; 		//Считываем значение кнопки Up
	 else {up = 0; paus_u = 10;}						//Если отпущена то 0
	if ((~PINB)&(1 << 3)) down++;	//Считываем значение кнопки Down
	 else {down = 0; paus_d = 10;} 					//Если отпущена то 0

   switch (tmp.a) //Поочерёдный вывод едениц и десятков
    {
	case 1: {
			 tmp.a = 0;	
			 PORTD = seg[ed]; 
			 sbi(PORTA, PA1); 
			 cbi(PORTA, PA0);
			} break;
   			
	case 0: {
			 tmp.a = 1; 
			 PORTD = seg[des]; 
			 cbi(PORTA, PA1); 
			 sbi(PORTA, PA0);
			}
	}
   
	_delay_ms(7);	

	ed     = 0;
	des    = 0;
	if (bit_is_set(TIMSK,TOIE1))	tmp.b = 1;
	else	tmp.b = 0; //Переписываем флаг прерывания Timer1 в переменную

	if(tmp.d == 1) {
					term_real = term_ac;
					tmp.d = 0;
				   }
	
	if (ac_up == 70)    {
						 ac_down = 0;
						 sbi(PORTB, PB2);
						 ac_up++;
						}
	 else {ac_up++;}
	if (ac_down == 170)  {
						 ac_up = 0;
						 cbi(PORTB, PB2);
						 ac_down++;
						 ACSR = 0x1A; //Взвод AC
						 cbi(PORTB,PB5);
						 term_ac = 0;
						 TCNT0 = 0;
						 sbi(TIMSK,TOIE0);
						}
	 else {ac_down++;}


	if (tmp.c == 1) {if (tmp.b == 0)
					 {
					  if (term_save != term_desire)
						{term_save = term_desire;
						 EEPROM_write(0x0002,term_save); //Запись желаемой температуры при переключении на отображение реальной
						 tmp.c = 0;
						 eeprom_log++;
						 EEPROM_write(0x0004,eeprom_log); //Количество записей в EPPROM
						 }
					 }
					}
	
	while (term_led !=	0) //Цикл деления буфера экрана на десятки и еденицы
					{
					 ed ++;
					 term_led--;
					 if (ed == 10) {ed = 0; des++;}
					 if (des == 10) des = 0;
					}
	switch (tmp.b)
		{case 0: {if (up > 10)   {
								 up = 0;
								 TCNT1 = 0;	   // Сбрасываем Timer1
								 sbi(TIMSK, TOIE1); // Разрещаем прерывание от Timer1
								 paus_u = 150;
								 cbi(PORTA, PA1); cbi(PORTA, PA0);
								 }
				  if (down > 10) {
								 down = 0;
								 TCNT1 = 0;	   // Сбрасываем Timer1
								 sbi(TIMSK, TOIE1); // Разрещаем прерывание от Timer1
								 paus_d = 150;
								 cbi(PORTA, PA1); cbi(PORTA, PA0);
								 }
				  term_led = term_real; //Запись в буфер экрана реальной температуры
				 } break;
		 case 1: {if (up > paus_u)  {if (term_desire < 55) term_desire++;	//Максимальное вводимое значение
								 up = 0;
								 TCNT1 = 0;	   // Сбрасываем Timer1
								 sbi(TIMSK, TOIE1); // Разрещаем прерывание от Timer1
								 paus_u = 40;
								 }
				  if (down > paus_d){if (term_desire > 5)  term_desire--;	//Минимальное вводимое значение
								 down = 0;
								 TCNT1 = 0;	   // Сбрасываем Timer1
								 sbi(TIMSK, TOIE1); // Разрещаем прерывание от Timer1
								 paus_d = 40;
								 }
				  term_led = term_desire; //Запись в буфер экрана желаемой температуры
				 tmp.c =1;
				 } break;
		}
	
	if (term_real > term_desire) sbi(PORTB, PB6);	//Сравнение желаемой и реальной температуры
	term_real += 1;
	if (term_real < term_desire) cbi(PORTB, PB6);	//и управление выходным ключём
	term_real -= 1;
		

	}       // закрывающая скобка бесконечного цикла

 }      // закрывающая скобка основной программы

SIGNAL(SIG_OVERFLOW1)  // Обработка прерывания от Timer1
	{cli();
	 cbi(TIMSK,TOIE1); // Отключаем прерывание Timer1	
	 tmp.c = 1;
	 sei();
}
SIGNAL(SIG_COMPARATOR) // Обработка прерывания от AC
	{cli();
	 ACSR = 0x00; //Сброс AC
	 tmp.d = 1;
	 sbi(PORTB,PB5);
	 cbi(TIMSK,TOIE0);
	 sei();
}
SIGNAL(SIG_OVERFLOW0)  // Обработка прерывания от Timer0
	{cli();
	 sbi(TIMSK,TOIE0);
	 term_ac++;
	 sei();
	}
