#include <Wire.h>
#include <RTClib.h>

// Определение пинов для подключения сдвиговых регистров
const int dataPin = 2;   // DS (pin 14) на 74HC595
const int latchPin = 3;   // ST_CP (pin 12) на 74HC595
const int clockPin = 4;   // SH_CP (pin 11) на 74HC595

// Объект для работы с RTC
RTC_DS3231 rtc;

// Массив с кодами для цифр на 7-сегментном индикаторе (общий катод)
// Биты: DP A B C D E F G
const byte digitPatterns[10] = {
  B00111111, // 0
  B00000110, // 1
  B01011011, // 2
  B01001111, // 3
  B01100110, // 4
  B01101101, // 5
  B01111101, // 6
  B00000111, // 7
  B01111111, // 8
  B01101111  // 9
};

void setup() {
  // Инициализация последовательного порта для отладки
  Serial.begin(9600);
  
  // Установка пинов в режим выхода
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  
  // Инициализация RTC
  if (!rtc.begin()) {
    Serial.println("Не удалось найти RTC");
    while (1);
  }

  // Если RTC потерял питание, установим время компиляции
  if (rtc.lostPower()) {
    Serial.println("RTC потерял питание, устанавливаем время компиляции!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  
  // Начальное состояние - все сегменты выключены
  updateShiftRegisters(0, 0, 0, 0);
}

void loop() {
  static unsigned long lastUpdate = 0;
  
  // Обновляем отображение чаще (для плавности)
  if (millis() - lastUpdate >= 200) {
    lastUpdate = millis();
    
    // Получаем текущее время от RTC
    DateTime now = rtc.now();
    
    // Обновляем отображение
    displayTime(now.hour(), now.minute());
  }
  
  // Здесь можно добавить обработку кнопок для настройки времени
}

void displayTime(byte hours, byte minutes) {
  // Разделяем часы и минуты на отдельные цифры
  byte hourTens = hours / 10;
  byte hourUnits = hours % 10;
  byte minuteTens = minutes / 10;
  byte minuteUnits = minutes % 10;
  
  // Получаем коды для каждой цифры
  byte digit1 = hourTens > 0 ? digitPatterns[hourTens] : 0; // Не показываем ноль в старшем разряде часов
  byte digit2 = digitPatterns[hourUnits];
  byte digit3 = digitPatterns[minuteTens];
  byte digit4 = digitPatterns[minuteUnits];
  
  // Добавляем двоеточие между часами и минутами (включено для digit2)
  //digit2 |= B10000000; // Устанавливаем бит DP
  
  // Отправляем данные в регистры
  updateShiftRegisters(digit1, digit2, digit3, digit4);
}

void updateShiftRegisters(byte digit1, byte digit2, byte digit3, byte digit4) {
  // Устанавливаем latchPin в LOW перед передачей данных
  digitalWrite(latchPin, LOW);
  
  // Передаем данные, начиная с последнего регистра (digit4)
  shiftOut(dataPin, clockPin, MSBFIRST, digit4);
  shiftOut(dataPin, clockPin, MSBFIRST, digit3);
  shiftOut(dataPin, clockPin, MSBFIRST, digit2);
  shiftOut(dataPin, clockPin, MSBFIRST, digit1);
  
  // Устанавливаем latchPin в HIGH для обновления выхода регистров
  digitalWrite(latchPin, HIGH);
}
74HC595
74HC595
74HC595
74HC595
GND5VSDASCLSQWRTCDS1307+