Загрузка данных


const int segPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
const int digitPins[] = {5, 4, 3, 2};
const int buttonPin = A2; // Кнопка на пине A2 (второй вывод на GND)

// Массив цифр для индикатора (0-9)
const byte charMasks[] = {
  0b11111100, // 0
  0b01100000, // 1
  0b11011010, // 2
  0b11110010, // 3
  0b01100110, // 4
  0b10110110, // 5
  0b10111110, // 6
  0b11100000, // 7
  0b11111110, // 8
  0b11110110  // 9
};

// Режимы: 0 - Секундомер, 1 - Таймер
int currentMode = 0; 

// Переменные для обработки кнопки (с поддержкой длинного нажатия)
bool lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
unsigned long buttonPressTime = 0;
bool longPressHandled = false;

// Переменные секундомера
unsigned long stopwatchMillis = 0;
unsigned long stopwatchStart = 0;
bool stopwatchRunning = false;

// Переменные таймера (установим старт по умолчанию, например, 1 минута = 60000 мс)
unsigned long timerTotalMillis = 60000; 
unsigned long timerRemaining = 60000;
unsigned long timerStart = 0;
bool timerRunning = false;

void setup() {
  for (int i = 0; i < 8; i++) {
    pinMode(segPins[i], OUTPUT);
  }
  
  for (int i = 0; i < 4; i++) {
    pinMode(digitPins[i], OUTPUT);
    digitalWrite(digitPins[i], HIGH);
  }

  pinMode(buttonPin, INPUT_PULLUP); // Кнопка замыкает пин на GND
}

void loop() {
  handleButton(); // Проверка нажатий кнопки

  // Выполнение логики выбранного режима
  if (currentMode == 0) {
    runStopwatch();
  } else {
    runTimer();
  }
}

// Функция обработки нажатий кнопки (короткое — старт/пауза, длинное (>1 сек) — смена режима)
void handleButton() {
  int reading = digitalRead(buttonPin);

  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading == LOW && lastButtonState == HIGH) {
      // Кнопку только что нажали
      buttonPressTime = millis();
      longPressHandled = false;
    } 
    else if (reading == LOW && lastButtonState == LOW) {
      // Кнопка удерживается
      if (!longPressHandled && (millis() - buttonPressTime > 1000)) {
        // Прошло больше 1 секунды — ДЛИННОЕ нажатие (смена режима)
        currentMode = !currentMode; // Переключение 0 <-> 1
        longPressHandled = true;

        // Сброс параметров при смене режима
        if (currentMode == 0) {
          stopwatchRunning = false;
          stopwatchMillis = 0;
        } else {
          timerRunning = false;
          timerRemaining = timerTotalMillis;
        }
      }
    } 
    else if (reading == HIGH && lastButtonState == LOW) {
      // Кнопку отпустили
      if (!longPressHandled) {
        // Это было КОРОТКОЕ нажатие (старт / пауза)
        if (currentMode == 0) {
          if (!stopwatchRunning) {
            stopwatchStart = millis() - stopwatchMillis;
            stopwatchRunning = true;
          } else {
            stopwatchRunning = false;
          }
        } else {
          if (!timerRunning) {
            if (timerRemaining == 0) timerRemaining = timerTotalMillis;
            timerStart = millis();
            timerRunning = true;
          } else {
            timerRunning = false;
          }
        }
      }
    }
  }
  lastButtonState = reading;
}

// --- РЕЖИМ 0: Секундомер ---
void runStopwatch() {
  unsigned long currentMillis = millis();
  if (stopwatchRunning) {
    stopwatchMillis = currentMillis - stopwatchStart;
  }

  int totalSeconds = stopwatchMillis / 1000;
  int minutes = (totalSeconds / 60) % 100;
  int seconds = totalSeconds % 60;

  int digits[4] = {
    minutes / 10,
    minutes % 10,
    seconds / 10,
    seconds % 10
  };

  displayDigits(digits);
}

// --- РЕЖИМ 1: Таймер ---
void runTimer() {
  if (timerRunning) {
    unsigned long elapsed = millis() - timerStart;
    if (elapsed >= timerRemaining) {
      timerRemaining = 0;
      timerRunning = false; // Таймер дошел до нуля
    } else {
      timerRemaining = timerRemaining - elapsed;
      timerStart = millis();
    }
  }

  int totalSeconds = timerRemaining / 1000;
  int minutes = (totalSeconds / 60) % 100;
  int seconds = totalSeconds % 60;

  int digits[4] = {
    minutes / 10,
    minutes % 10,
    seconds / 10,
    seconds % 10
  };

  displayDigits(digits);
}

// Функция динамической индикации 4 цифр
void displayDigits(int digits[]) {
  for (int d = 0; d < 4; d++) {
    digitalWrite(digitPins[d], HIGH); // Выключаем предыдущий разряд
    
    byte mask = charMasks[digits[d] & 7]; // Ограничиваем индекс от 0 до 9
    for (int s = 0; s < 8; s++) {
      bool bitVal = bitRead(mask, 7 - s);
      digitalWrite(segPins[s], bitVal);
    }

    digitalWrite(digitPins[d], LOW); // Включаем текущий разряд
    delay(4); // Время свечения разряда для мультиплексирования
  }
}