#include <Arduino.h>
#include <LiquidCrystal_I2C.h>

// Определение пинов для подключения компонентов
#define ENCODER_CLK_PIN A1  // Пин CLK энкодера
#define ENCODER_DT_PIN A2   // Пин DT энкодера
#define ENCODER_SW_PIN A3   // Пин кнопки энкодера

// Настройки LCD дисплея
#define LCD_ADDRESS 0x27    // I2C адрес LCD дисплея
#define LCD_COLS 20         // Количество столбцов дисплея
#define LCD_ROWS 4          // Количество строк дисплея
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLS, LCD_ROWS);

// Параметры таймера
volatile uint8_t current_day = 0;     // день (обновляется каждый день)
volatile uint8_t current_hour = 0;    // час (обновляется каждый час)
volatile uint8_t current_minute = 0;  // минуты
volatile uint8_t current_second = 0;  // секунды

// Функция установки даты и времени
void set_date_and_time() {
  // Переменные для хранения позиции курсора и значений
  int cursor_pos = 0;
  int values[3] = {current_day, current_hour, current_minute};
  int limits[3] = {21, 23, 59}; // Максимальные значения
  bool editing = false;
  
  lcd.clear();
  while(true) {
    // Отображаем текущие значения
    lcd.setCursor(0, 0);
    lcd.print("Set Date / Time:");
    lcd.setCursor(0, 1); 
    lcd.print("Day:    %02d");
    lcd.print(values[0]);
    lcd.setCursor(0, 2);
    lcd.print("Hour:   %02d");
    lcd.print(values[1]);  
    lcd.setCursor(0, 3);
    lcd.print("Minute: %02d");
    lcd.print(values[2]);

    // Мигающий курсор на редактируемой позиции
    lcd.setCursor(8, cursor_pos + 1);
    lcd.blink();

    // Обработка энкодера
    if (digitalRead(ENCODER_SW_PIN) == LOW) {
      delay(50);
      if (!editing) {
        editing = true;
      } else {
        editing = false;
        cursor_pos++;
        if (cursor_pos > 2) {
          // Сохраняем значения и выходим
          current_day = values[0];
          current_hour = values[1]; 
          current_minute = values[2];
          break;
        }
      }
      while(digitalRead(ENCODER_SW_PIN) == LOW);
    }

    if (editing) {
      // Изменение значения энкодером
      if (digitalRead(ENCODER_CLK_PIN) != digitalRead(ENCODER_DT_PIN)) {
        if (digitalRead(ENCODER_CLK_PIN) == LOW) {
          values[cursor_pos]++;
          if (values[cursor_pos] > limits[cursor_pos]) values[cursor_pos] = 0;
        } else {
          values[cursor_pos]--;
          if (values[cursor_pos] < 0) values[cursor_pos] = limits[cursor_pos];
        }
        delay(2);
      }
    }
  }
  
  lcd.noBlink();
  lcd.clear();
}


/* -------------------- Таймер: день, часы, минуты, секунды --------------------
 */
ISR(TIMER1_OVF_vect) {
    if (++current_second >=
      60)  // Увеличеваем счетчик секунд пока не достигнет 60
    {
      current_second = 0;  // Обнуляем сукунды
      if (++current_minute >=
        60)  // Увеличеваем счетчик минут пока не достигнет 60
      {
        current_minute = 0;  // Обнуляем минуты
        if (++current_hour >=
          24)  // Увеличеваем часов секунд пока не достигнет 24
        {
          current_hour = 0;  // Обнуляем часы
          ++current_day;     // Увеличеваем счетчик дней
        }
      }
    }
}

void setup()
{
  lcd.init();                             // Инициируем работу с LCD дисплеем
  lcd.backlight();                        // Turn on the LCD backlight
  lcd.print(F("=< EGG  INCUBATOR >="));  // Приветственный экран
  delay(500);

  lcd.setCursor(0, 3);
  lcd.print(F("Starting"));
  for (int i = 0; i < 12; ++i) {
    lcd.print('.');
    delay(300);
  }

  /* -------------------- Настройка таймера -------------------- */
  cli();                  // отключить глобальные прерывания
  TCCR1A = 0;             // установить TCCR1A регистр в 0
  TCCR1B = 0;             // установить TCCR1B регистр в 0
  TCCR1A = (1 << WGM11);  // режим 14 FAST PWM
  TCCR1B = (1 << CS12) | (1 << WGM13) | (1 << WGM12);  // делить частоту CPU на 256
  ICR1 = 62499;           // (16000000MHz / div 256) - 1 = 1 раз в секунду
  TIMSK1 = (1 << TOIE1);  // разрешить прерывание
  sei();                  // включить глобальные прерывания

  lcd.clear();                 // очищаем экран

  set_date_and_time();

}

/* Основной цикл программы */
void loop()
{

}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module