diff --git a/libs/hardware/InputManager/include/InputManager.h b/libs/hardware/InputManager/include/InputManager.h new file mode 100644 index 0000000..d03e351 --- /dev/null +++ b/libs/hardware/InputManager/include/InputManager.h @@ -0,0 +1,59 @@ +#ifndef INPUT_MANAGER_H +#define INPUT_MANAGER_H + +#include + +class InputManager { + public: + InputManager(); + void begin(); + uint8_t getState(); + void update(); + bool isPressed(uint8_t buttonIndex); + bool wasPressed(uint8_t buttonIndex); + bool wasReleased(uint8_t buttonIndex); + + // Button indices + static const uint8_t BTN_BACK = 0; + static const uint8_t BTN_CONFIRM = 1; + static const uint8_t BTN_LEFT = 2; + static const uint8_t BTN_RIGHT = 3; + static const uint8_t BTN_UP = 4; + static const uint8_t BTN_DOWN = 5; + static const uint8_t BTN_POWER = 6; + + // Power button methods + bool isPowerButtonPressed(); + + // Button names + static const char* getButtonName(uint8_t buttonIndex); + + private: + int getButtonFromADC(int adcValue, const int thresholds[], int numButtons); + + uint8_t currentState; + uint8_t lastState; + uint8_t pressedEvents; + uint8_t releasedEvents; + unsigned long lastDebounceTime; + unsigned long powerButtonPressStart; + bool powerButtonWasPressed; + + static const int BUTTON_ADC_PIN_1 = 1; + static const int NUM_BUTTONS_1 = 4; + static const int ADC_THRESHOLDS_1[]; + + static const int POWER_BUTTON_PIN = 3; + + static const int BUTTON_ADC_PIN_2 = 2; + static const int NUM_BUTTONS_2 = 2; + static const int ADC_THRESHOLDS_2[]; + + static const int ADC_TOLERANCE = 200; + static const int ADC_NO_BUTTON = 3800; + static const unsigned long DEBOUNCE_DELAY = 5; + + static const char* BUTTON_NAMES[]; +}; + +#endif diff --git a/libs/hardware/InputManager/library.json b/libs/hardware/InputManager/library.json new file mode 100644 index 0000000..b61ecde --- /dev/null +++ b/libs/hardware/InputManager/library.json @@ -0,0 +1,14 @@ +{ + "name": "InputManager", + "version": "1.0.0", + "description": "Button inputs", + "authors": [ + { + "name": "CidVonHighwind", + "url": "https://github.com/CidVonHighwind" + } + ], + "dependencies": {}, + "platforms": "espressif32", + "frameworks": ["arduino", "espidf"] +} diff --git a/libs/hardware/InputManager/src/InputManager.cpp b/libs/hardware/InputManager/src/InputManager.cpp new file mode 100644 index 0000000..17fdb42 --- /dev/null +++ b/libs/hardware/InputManager/src/InputManager.cpp @@ -0,0 +1,116 @@ +#include "InputManager.h" + +const int InputManager::ADC_THRESHOLDS_1[] = {3470, 2655, 1470, 3}; +const int InputManager::ADC_THRESHOLDS_2[] = {2205, 3}; +const char* InputManager::BUTTON_NAMES[] = {"Back", "Confirm", "Left", "Right", "Up", "Down", "Power"}; + +InputManager::InputManager() + : currentState(0), + lastState(0), + pressedEvents(0), + releasedEvents(0), + lastDebounceTime(0), + powerButtonPressStart(0), + powerButtonWasPressed(false) {} + +void InputManager::begin() { + pinMode(BUTTON_ADC_PIN_1, INPUT); + pinMode(BUTTON_ADC_PIN_2, INPUT); + pinMode(POWER_BUTTON_PIN, INPUT_PULLUP); + analogSetAttenuation(ADC_11db); +} + +int InputManager::getButtonFromADC(int adcValue, const int thresholds[], int numButtons) { + if (adcValue > ADC_NO_BUTTON) { + return -1; + } + + for (int i = 0; i < numButtons; i++) { + if (abs(adcValue - thresholds[i]) < ADC_TOLERANCE) { + return i; + } + } + + return -1; +} + +uint8_t InputManager::getState() { + uint8_t state = 0; + + // Read GPIO1 buttons + int adcValue1 = analogRead(BUTTON_ADC_PIN_1); + int button1 = getButtonFromADC(adcValue1, ADC_THRESHOLDS_1, NUM_BUTTONS_1); + if (button1 >= 0) { + state |= (1 << button1); + } + + // Read GPIO2 buttons + int adcValue2 = analogRead(BUTTON_ADC_PIN_2); + int button2 = getButtonFromADC(adcValue2, ADC_THRESHOLDS_2, NUM_BUTTONS_2); + if (button2 >= 0) { + state |= (1 << (button2 + 4)); + } + + // Read power button (digital, active LOW) + if (digitalRead(POWER_BUTTON_PIN) == LOW) { + state |= (1 << BTN_POWER); + } + + return state; +} + +void InputManager::update() { + unsigned long currentTime = millis(); + uint8_t state = getState(); + + // Always clear events first + pressedEvents = 0; + releasedEvents = 0; + + // Debounce + if (state != lastState) { + lastDebounceTime = currentTime; + lastState = state; + } + + if ((currentTime - lastDebounceTime) > DEBOUNCE_DELAY) { + if (state != currentState) { + // Calculate pressed and released events + pressedEvents = state & ~currentState; + releasedEvents = currentState & ~state; + currentState = state; + + // Track power button press timing + if (pressedEvents & (1 << BTN_POWER)) { + powerButtonPressStart = currentTime; + powerButtonWasPressed = true; + } + if (releasedEvents & (1 << BTN_POWER)) { + powerButtonWasPressed = false; + } + } + } +} + +bool InputManager::isPressed(uint8_t buttonIndex) { + return currentState & (1 << buttonIndex); +} + +bool InputManager::wasPressed(uint8_t buttonIndex) { + return pressedEvents & (1 << buttonIndex); +} + +bool InputManager::wasReleased(uint8_t buttonIndex) { + return releasedEvents & (1 << buttonIndex); +} + +const char* InputManager::getButtonName(uint8_t buttonIndex) { + if (buttonIndex <= BTN_POWER) { + return BUTTON_NAMES[buttonIndex]; + } + return "Unknown"; +} + +bool InputManager::isPowerButtonPressed() { + return isPressed(BTN_POWER); +}