| 8 | static const auto LOGGER = tt::Logger("ButtonControl"); |
| 9 | |
| 10 | ButtonControl::ButtonControl(const std::vector<PinConfiguration>& pinConfigurations) |
| 11 | : buttonQueue(20, sizeof(ButtonEvent)), |
| 12 | pinConfigurations(pinConfigurations) { |
| 13 | |
| 14 | pinStates.resize(pinConfigurations.size()); |
| 15 | |
| 16 | // Build isrArgs with one entry per unique physical pin, then configure GPIO. |
| 17 | isrArgs.reserve(pinConfigurations.size()); |
| 18 | for (size_t i = 0; i < pinConfigurations.size(); i++) { |
| 19 | const auto pin = static_cast<gpio_num_t>(pinConfigurations[i].pin); |
| 20 | |
| 21 | // Skip if this physical pin was already seen. |
| 22 | bool seen = false; |
| 23 | for (const auto& arg : isrArgs) { |
| 24 | if (arg.pin == pin) { seen = true; break; } |
| 25 | } |
| 26 | if (seen) continue; |
| 27 | |
| 28 | gpio_config_t io_conf = { |
| 29 | .pin_bit_mask = 1ULL << pin, |
| 30 | .mode = GPIO_MODE_INPUT, |
| 31 | .pull_up_en = GPIO_PULLUP_DISABLE, |
| 32 | .pull_down_en = GPIO_PULLDOWN_DISABLE, |
| 33 | .intr_type = GPIO_INTR_ANYEDGE, |
| 34 | }; |
| 35 | esp_err_t err = gpio_config(&io_conf); |
| 36 | if (err != ESP_OK) { |
| 37 | LOGGER.error("Failed to configure GPIO {}: {}", static_cast<int>(pin), esp_err_to_name(err)); |
| 38 | continue; |
| 39 | } |
| 40 | |
| 41 | // isrArgs is reserved upfront; push_back will not reallocate, keeping addresses stable |
| 42 | // for gpio_isr_handler_add() called later in startThread(). |
| 43 | isrArgs.push_back({ .self = this, .pin = pin }); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | ButtonControl::~ButtonControl() { |
| 48 | if (driverThread != nullptr && driverThread->getState() != tt::Thread::State::Stopped) { |