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


#include <Keyboard.h>

// Пины джойстика
const int JOY_X_PIN = A0;
const int JOY_Y_PIN = A1;

// Пороги срабатывания джойстика
const int THRESHOLD = 400;
const int DEADZONE = 100;

// Переменные для отслеживания состояния
bool wPressed = false;
bool aPressed = false;
bool sPressed = false;
bool dPressed = false;

// Пины кнопок (5-13)
const int buttonPins[] = {5, 6, 7, 8, 9, 10, 11, 12, 13};
const char keys[] = {'Q', 'E', 'R', 'F', 'Z', 'X', 'C', 'V', 'B'};
const int numButtons = 9;

bool buttonStates[numButtons];

// СТАБИЛИЗАЦИЯ: таймеры и сброс состояния
unsigned long lastActivityTime = 0;
const unsigned long RESET_TIMEOUT = 5000; // 5 секунд без активности - полный сброс
unsigned long lastResetCheck = 0;

// Для дебаунса
const int DEBOUNCE_DELAY = 10;
unsigned long lastButtonTime[numButtons];
unsigned long lastJoystickTime = 0;
int lastX = 512, lastY = 512;

void setup() {
  Serial.begin(9600);
  Keyboard.begin();
  
  for (int i = 0; i < numButtons; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
    buttonStates[i] = false;
    lastButtonTime[i] = 0;
  }
  
  // ПРИНУДИТЕЛЬНЫЙ СБРОС при старте
  resetAllKeys();
  delay(100);
  
  Serial.println("Джойстик-клавиатура запущена (стабильная версия)");
}

void loop() {
  checkAndResetIfNeeded();  // Критически важно!
  
  int xValue = analogRead(JOY_X_PIN);
  int yValue = analogRead(JOY_Y_PIN);
  
  processJoystick(xValue, yValue);
  processButtons();
  
  delay(5); // Маленькая задержка для стабильности
}

void processJoystick(int x, int y) {
  // Дебаунс для джойстика
  if (millis() - lastJoystickTime < 20) return;
  
  bool hasActivity = false;
  
  // Вертикаль (W/S)
  if (y < 512 - THRESHOLD) {
    if (!wPressed) {
      Keyboard.press('W');
      wPressed = true;
      hasActivity = true;
      Serial.println("W");
    }
  } else if (y > 512 + THRESHOLD) {
    if (!sPressed) {
      Keyboard.press('S');
      sPressed = true;
      hasActivity = true;
      Serial.println("S");
    }
  } else {
    if (wPressed) {
      Keyboard.release('W');
      wPressed = false;
      hasActivity = true;
    }
    if (sPressed) {
      Keyboard.release('S');
      sPressed = false;
      hasActivity = true;
    }
  }
  
  // Горизонталь (A/D)
  if (x < 512 - THRESHOLD) {
    if (!aPressed) {
      Keyboard.press('A');
      aPressed = true;
      hasActivity = true;
      Serial.println("A");
    }
  } else if (x > 512 + THRESHOLD) {
    if (!dPressed) {
      Keyboard.press('D');
      dPressed = true;
      hasActivity = true;
      Serial.println("D");
    }
  } else {
    if (aPressed) {
      Keyboard.release('A');
      aPressed = false;
      hasActivity = true;
    }
    if (dPressed) {
      Keyboard.release('D');
      dPressed = false;
      hasActivity = true;
    }
  }
  
  if (hasActivity) {
    lastActivityTime = millis();
  }
  
  lastJoystickTime = millis();
}

void processButtons() {
  unsigned long now = millis();
  bool hasActivity = false;
  
  for (int i = 0; i < numButtons; i++) {
    if (now - lastButtonTime[i] < DEBOUNCE_DELAY) continue;
    
    bool currentState = (digitalRead(buttonPins[i]) == LOW);
    
    if (currentState != buttonStates[i]) {
      if (currentState) {
        Keyboard.press(keys[i]);
        Serial.print("Нажата: ");
        Serial.println(keys[i]);
      } else {
        Keyboard.release(keys[i]);
        Serial.print("Отпущена: ");
        Serial.println(keys[i]);
      }
      buttonStates[i] = currentState;
      lastButtonTime[i] = now;
      hasActivity = true;
    }
  }
  
  if (hasActivity) {
    lastActivityTime = now;
  }
}

// КРИТИЧЕСКИ ВАЖНАЯ ФУНКЦИЯ - сбрасывает все клавиши
void resetAllKeys() {
  // Список всех возможных клавиш, которые могли быть нажаты
  const char* allKeys[] = {"W", "A", "S", "D", "Q", "E", "R", "F", "Z", "X", "C", "V", "B"};
  
  for (int i = 0; i < 13; i++) {
    Keyboard.release(allKeys[i][0]);
  }
  
  // Сброс внутренних состояний
  wPressed = false;
  aPressed = false;
  sPressed = false;
  dPressed = false;
  
  for (int i = 0; i < numButtons; i++) {
    buttonStates[i] = false;
  }
  
  Serial.println("!!! ПОЛНЫЙ СБРОС КЛАВИШ !!!");
}

// Проверка и автоматический сброс при зависании
void checkAndResetIfNeeded() {
  unsigned long now = millis();
  
  // Периодическая проверка каждые 100мс
  if (now - lastResetCheck < 100) return;
  lastResetCheck = now;
  
  // Если нет активности дольше таймаута - сброс
  if (now - lastActivityTime > RESET_TIMEOUT) {
    // Дополнительная проверка: действительно ли винда зависла?
    if (wPressed || aPressed || sPressed || dPressed) {
      Serial.println("Обнаружен зависший джойстик - сброс");
      resetAllKeys();
      lastActivityTime = now;
    }
    
    // Проверка кнопок
    bool anyPressed = false;
    for (int i = 0; i < numButtons; i++) {
      if (buttonStates[i]) {
        anyPressed = true;
        break;
      }
    }
    
    if (anyPressed) {
      Serial.println("Обнаружены зависшие кнопки - сброс");
      resetAllKeys();
      lastActivityTime = now;
    }
  }
  
  // АВТОМАТИЧЕСКИЙ СБРОС КАЖДЫЕ 2 МИНУТЫ (страховка)
  static unsigned long lastAutoReset = 0;
  if (now - lastAutoReset > 120000) { // 2 минуты
    Serial.println("Плановый профилактический сброс");
    resetAllKeys();
    lastAutoReset = now;
    lastActivityTime = now;
  }
}