#include <OneWire.h>
#include <EEPROM.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#define BUTTON 13 // 
#define RELAY 8  // 
#define BUZZER 7 // 
#define ENCODER1_PIN 1  //  ()   
#define ENCODER2_PIN 2  //  ()    
#define RES_PIN 4// 
boolean buz=false;

#define PAUSE 4  // .   
#define LOWPAUSE 30 //15 .     
  
#define RES_KEY_FLAG_ 0x76  //    
byte bytes[4];
boolean is_res_keys = false;
boolean is_encoder_1 = false;
boolean is_encoder_2 = false;
//-----------------------------------------
//-       -
//----------------------------------------
unsigned long  res_dt = 0; 
unsigned long  res_dt_sum=0; 
#define RES_DT_COUNT 500 //   
#define RES_DT_SKIP_COUNT 100 //  ,     
#define RES_DT_POINT 6 // 
int res_dt_n = 0;
unsigned long res_key=0;
unsigned long res_key_old=0;
unsigned long res_key_wait_first = 500;  //      
unsigned long res_key_wait_next = 250;  //      
unsigned long res_key_wait_millis = 0;
unsigned long res_key_millis;
unsigned long res_key_array[51][2];
unsigned int res_key_count = 0;
unsigned int res_key_delta = 3;

//-----------------------------------------
//-           -
//-----------------------------------------
unsigned long encoder1_dt;
unsigned long encoder1_key=0;
unsigned long encoder1_key_old=0;
int encoder1_key1 = 0;
int encoder1_key2 = 0;
int encoder1_key3 = 0;
unsigned long encoder1_millis;
unsigned long encoder1_wait_millis=1;
unsigned long encoder1_key_wait = 500;  //       
unsigned long encoder1_key_wait_millis;
unsigned long encoder1_key_millis;
unsigned long encoder1_dt_sum = 0;  
int encoder1_dt_n = 0;
//-----------------------------------------
//-           -
//-----------------------------------------
unsigned long encoder2_dt;
unsigned long encoder2_key=0;
unsigned long encoder2_key_old=0;
int encoder2_key1 = 0;
int encoder2_key2 = 0;
int encoder2_key3 = 0;
unsigned long encoder2_millis;
unsigned long encoder2_wait_millis=1;
unsigned long encoder2_key_wait = 500;  //       
unsigned long encoder2_key_wait_millis;
unsigned long encoder2_key_millis;

//-      
//------------------------------------------------------
unsigned char volt_set=118; //11.8 .  .  .
boolean pc_on=false;
boolean lowvolt=false;
unsigned char lowtime=0;

byte buttontime=0;
boolean state=false;
boolean a=false;

ISR(TIMER1_COMPA_vect) 
{
  TCNT1H=0x00;
  TCNT1L=0x00;
  if (digitalRead(BUTTON) == LOW)
  {
    buttontime++;
    if(buttontime>PAUSE && !a)
    {
      if(!pc_on && (getvolt()>=volt_set))
      {
        buz=true;
        digitalWrite(RELAY, HIGH);
        pc_on=true;
        a=true;
        lowvolt=false;
        lowtime=0;
      }
      else
      {
        buz=true;
        digitalWrite(RELAY, LOW);
        pc_on=false;
        a=true;
      }
    }
  }
  if(lowvolt && pc_on)
  {
    lowtime++;
    if(lowtime>=LOWPAUSE)
    {
      digitalWrite(RELAY, LOW);
      pc_on=false;
    }
  }
} 

void setup() 
{ 
  Serial.begin(115200);
  pinMode(RELAY,OUTPUT);  
  pinMode(BUZZER,OUTPUT);
  pinMode(BUTTON,INPUT); 
  digitalWrite(BUTTON, HIGH); //   
  TCCR1A=0x00;
  TCCR1B=0x04;
  TCNT1H=0x00;
  TCNT1L=0x00;
  OCR1AH=0x7A;
  OCR1AL=0x12;
  TIMSK1=0x02; 
    
    encoder1_key_millis = millis();
    encoder2_key_millis = millis();
    encoder1_millis = millis();
    encoder2_millis = millis();
    
    res_key_millis = millis();
    encoder1_key_wait_millis=encoder1_key_wait;
    encoder2_key_wait_millis=encoder2_key_wait;
    
    unsigned int first_run_key = EEPROM.read(0);
    if ( first_run_key == RES_KEY_FLAG_ )
    {
      res_key_count = EEPROM.read(1);
      //EEPROM.write(addr, val);
      for(int i=0; i<res_key_count;i++) 
      { 
        res_key_array[i][0] = (EEPROM.read(i+2) * 256) + EEPROM.read(i+2+50) - res_key_delta; res_key_array[i][1] = res_key_array[i][0] + res_key_delta + res_key_delta; 
      }
    }
    for(int i=res_key_count; i<51;i++) 
    { 
      res_key_array[i][0] = 0xFFFFFFFF; res_key_array[i][1] = 0xFFFFFFFF; 
    }
}
 
void loop() 
{
  if (Serial.available() >= 1) //     
  {
     switch (Serial.read())
    {
      case 0x04: //      
       is_encoder_1 = true;
       Serial.println("ENC1 ON");
     break;

     case 0x05: //      
       is_encoder_2 = true;
       Serial.println("ENC2 ON");
     break;
     
      case 0x06: //      
       is_res_keys = true;
     break;
     
     case 0x84: //      
       is_encoder_1 = false;
       Serial.println("ENC1 OFF");
     break;

     case 0x85: //      
       is_encoder_2 = false;
       Serial.println("ENC2 OFF");
     break;

     case 0x86: //      
       is_res_keys = false;
     break;

     case 0xAA: //      
     {
       while (Serial.available() < 5) {}
       int i = Serial.read();
       bytes[0] = Serial.read();          //   4-  
       bytes[1] = Serial.read();  
       bytes[2] = Serial.read(); 
       bytes[3] = Serial.read(); 
       unsigned long key_res_min = 0; key_res_min = bytes[0]; key_res_min = key_res_min * 256 + bytes[1];  
       unsigned long key_res_max = 0; key_res_max = bytes[2]; key_res_max = key_res_max * 256 + bytes[3];  
       res_key_array[i-1][0] = key_res_min; 
       res_key_array[i-1][1] = key_res_max;
     }
     break;

     case 0xAB: //      EEPROM
     {
       EEPROM.write(0,0); //    
       res_key_count = 0; //     
       EEPROM.write(1,0); //
       for(int i=0; i<51;i++) 
       { 
        res_key_array[i][0] = 0xFFFFFFFF; res_key_array[i][1] = 0xFFFFFFFF; 
       }
     } 
     break;
    }
  } 
  
  if( is_encoder_1 ) encoder_1();                      //   
  if( is_encoder_2 ) encoder_2();                      //   
  if( is_res_keys ) res_keys();                        //   
  
  if(pc_on)// 
  {
    if(getvolt()<volt_set)
    {
      lowvolt=true;
    }
    else
    {
      lowvolt=false;
      lowtime=0;
    }
  }
  if (digitalRead(BUTTON) == HIGH)
  {
      a=false;
      buttontime=0;
  }
  if(buz)
  {
    //   
    //:
    digitalWrite(BUZZER, HIGH);
    delay(150);
    digitalWrite(BUZZER, LOW);
    buz=false;
  }
}

unsigned char getvolt()// 
{
  float u=0.0;
  unsigned char volt=0;
  u=analogRead(0);
  volt=(u*200.0)/1023.0;
  return volt;
}

//----------------------------------------------------------------------------------
//     
//----------------------------------------------------------------------------------
void encoder_1()
{
  if( encoder1_key_millis + encoder1_key_wait_millis*2 < millis() ) { encoder1_key_old = 0; }
  if( encoder1_millis + encoder1_wait_millis < millis() )
  {
    encoder1_millis = millis();
    encoder1_dt = analogRead(ENCODER1_PIN); //   
    
    if( encoder1_dt >= 0x246 && encoder1_dt <= 0x286 )
    { //    
      encoder1_key = ENCODER1_PIN;
      encoder1_key = (encoder1_key << 16) | 0x030000EE;
      if ( encoder1_key == encoder1_key_old )
      { //    
        if( encoder1_key_millis + encoder1_key_wait_millis < millis() )
        { 
          bytes[0] = encoder1_key & 0xFF;          //   4-  
          bytes[1] = (encoder1_key & 0xFF00) >> 8;  
          bytes[2] = (encoder1_key & 0xFF0000) >> 16; 
          bytes[3] = (encoder1_key & 0xFF000000) >> 24;
          Serial.write( bytes,4); //    
          encoder1_key_millis = millis(); encoder1_key_wait_millis = encoder1_key_wait; //ir_wait_next;
        }
      }
      else 
      { //     
        encoder1_key_millis = millis(); encoder1_key_wait_millis = 50; //ir_wait_first;
      } 
      encoder1_key_old = encoder1_key;
    } 
    else
    {
      if( encoder1_dt >= 0x3E0 && encoder1_dt <= 0x410 && encoder1_key3 != 1 )
      {
        if( (encoder1_key2 == 2) && (encoder1_key3 == 3))
        { 
          bytes[0] = 0xEE;          //   2- 
          bytes[1] = 0; 
          bytes[2] = ENCODER1_PIN;
          bytes[3] = 1;
          Serial.write( bytes,4); //         
        }
        else
        {
          if( (encoder1_key2 == 3) && (encoder1_key3 == 2) )
          {
            bytes[0] = 0xEE;          //   2- 
            bytes[1] = 0; 
            bytes[2] = ENCODER1_PIN;
            bytes[3] = 2;
            Serial.write( bytes,4); //         
          }
        }
        encoder1_key1=encoder1_key2; encoder1_key2=encoder1_key3; encoder1_key3=1;
      }
      else
      {
        if( encoder1_dt >= 0xA0 && encoder1_dt <= 0xF0 && encoder1_key3 != 2 )
        {
          encoder1_key1=encoder1_key2; encoder1_key2=encoder1_key3; encoder1_key3=2;
        }
        else
        {
          if( encoder1_dt >= 0x1A0 && encoder1_dt <= 0x200 && encoder1_key3 != 3 )
          {
            encoder1_key1=encoder1_key2; encoder1_key2=encoder1_key3; encoder1_key3=3;
          }
        }
      }
    }
  }
}
//----------------------------------------------------------------------------------
//     
//----------------------------------------------------------------------------------
void encoder_2()
{  
  if( encoder2_key_millis + encoder2_key_wait_millis*2 < millis() ) { encoder2_key_old = 0; }
  if( encoder2_millis + encoder2_wait_millis < millis() )
  {
    encoder2_millis = millis();
    encoder2_dt = analogRead(ENCODER2_PIN); //   
    if( encoder2_dt >= 0x246 && encoder2_dt <= 0x286 )
    { //    
      encoder2_key = ENCODER2_PIN;
      encoder2_key = (encoder2_key << 16) | 0x030000EE;
      if ( encoder2_key == encoder2_key_old )
      { //    
        if( encoder2_key_millis + encoder2_key_wait_millis < millis() )
        { 
          bytes[0] = encoder2_key & 0xFF;          //   4-  
          bytes[1] = (encoder2_key & 0xFF00) >> 8;  
          bytes[2] = (encoder2_key & 0xFF0000) >> 16; 
          bytes[3] = (encoder2_key & 0xFF000000) >> 24; 
          Serial.write( bytes,4); //    
          encoder2_key_millis = millis(); encoder2_key_wait_millis = encoder2_key_wait; //ir_wait_next;
        }
      }
      else 
      { //     
        encoder2_key_millis = millis(); encoder2_key_wait_millis = 50; //ir_wait_first;
      } 
      encoder2_key_old = encoder2_key;
    } 
    else
    {
      if( encoder2_dt >= 0x3E0 && encoder2_dt <= 0x410 && encoder2_key3 != 1 )
      {
        if( (encoder2_key2 == 2) && (encoder2_key3 == 3))
        { 
          bytes[0] = 0xEE;          //   2- 
          bytes[1] = 0; 
          bytes[2] = ENCODER2_PIN;
          bytes[3] = 1;
          Serial.write( bytes,4); //         
        }
        else
        {
          if( (encoder2_key2 == 3) && (encoder2_key3 == 2) )
          {
            bytes[0] = 0xEE;          //   2- 
            bytes[1] = 0; 
            bytes[2] = ENCODER2_PIN;
            bytes[3] = 2;
            Serial.write( bytes,4); //         
          }
        }
        encoder2_key1=encoder2_key2; encoder2_key2=encoder2_key3; encoder2_key3=1;
      }
      else
      {
        if( encoder2_dt >= 0xA0 && encoder2_dt <= 0xF0 && encoder2_key3 != 2 )
        {
          encoder2_key1=encoder2_key2; encoder2_key2=encoder2_key3; encoder2_key3=2;
        }
        else
        {
          if( encoder2_dt >= 0x1A0 && encoder2_dt <= 0x200 && encoder2_key3 != 3 )
          {
            encoder2_key1=encoder2_key2; encoder2_key2=encoder2_key3; encoder2_key3=3;
          }
        }
      }
    }
  }
}

//----------------------------------------------------------------------------------
//     
//----------------------------------------------------------------------------------
void res_keys()
{  
  {
    res_dt = analogRead(RES_PIN); //    
    if( res_dt >= 0x05 && res_dt <= 0x3F0 )
    { 
      res_dt_n++;
      if( res_dt_n > RES_DT_SKIP_COUNT )
      {
        res_dt_sum += (res_dt << RES_DT_POINT);
        if( res_dt_n == RES_DT_COUNT)
        { 

          res_key = (res_dt_sum / (RES_DT_COUNT - RES_DT_SKIP_COUNT));
          res_key = (((((( res_dt_sum / (( RES_DT_COUNT - RES_DT_SKIP_COUNT ) + (2^(RES_DT_POINT-1)-1) ) >> (RES_DT_POINT-1)) + 1) >> 1) + 1)>> 1)); // + 1) >> 1;
          res_dt_sum = 0; res_dt_n = 0;
        }
       }
    }
    else
    {
      res_dt_sum = 0; res_dt_n = 0; res_key = 0;
      res_key_wait_millis = 0;
    }
  }
  if( res_key_millis + res_key_wait_millis*2 <= millis() ) { res_key_old = 0; }
  if( res_key_millis + res_key_wait_millis <= millis() )
  {
    if( res_key != 0 )
    {
      if( ((res_key_old - res_key_delta) <=  res_key) && (res_key <= (res_key_old + res_key_delta)) )
      {
        res_key_millis = millis(); res_key_wait_millis = res_key_wait_next;
      }
      else
      {
        res_key_millis = millis(); res_key_wait_millis = res_key_wait_first;
      }

        int i = 0; int exit = 0;
        while( res_key_array[i][0] != 0xFFFFFFFF && exit == 0 )
        {
          if( (res_key_array[i][0] <= res_key) && (res_key <= res_key_array[i][1]) ) exit = 1; else i++;
        }
        if( exit == 1 ) 
        { 
          bytes[0] = 0xAA;          //   4-  
          bytes[1] = 0;  
          bytes[2] = RES_PIN; 
          bytes[3] = i+1; 
          Serial.write( bytes,4); //    
        }
        else
        {
          if( res_key_count < 50 )
          {
            res_key_array[res_key_count][0] = res_key - res_key_delta; res_key_array[res_key_count][1] = res_key + res_key_delta;
            res_key_count++;
            
            EEPROM.write(1, res_key_count); //   
            byte one_byte = res_key / 256;
            EEPROM.write(res_key_count+1, one_byte ); //     
            one_byte = res_key - one_byte * 256;
            EEPROM.write(res_key_count+1+50, one_byte ); //     
            EEPROM.write(0, RES_KEY_FLAG_);
          
            bytes[0] = 0xAA;          //   4-  
            bytes[1] = 0;  
            bytes[2] = RES_PIN; 
            bytes[3] = res_key_count; 
            Serial.write( bytes,4); //    
          }
          else
          {
            bytes[0] = 0xAA;          //   4-  
            bytes[1] = 0xAA;  
            bytes[2] = (res_key & 0xFF00) >> 8; 
            bytes[3] = res_key & 0xFF; 
            Serial.write( bytes,4); //    
          }
        }
    }
    res_key_old = res_key;
  }
}