/* * * Copyright (c) 2022 Project CHIP Authors * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file Button.cpp * * Implements a Button tied to a GPIO and provides debouncing * **/ #include "driver/gpio.h" #include "esp_check.h" #include "esp_log.h" #include "esp_system.h" #include "AppTask.h" #include "Button.h" #include "Globals.h" #include #include #include static const char TAG[] = "Button.cpp"; extern Button gButtons[BUTTON_NUMBER]; Button::Button() {} Button::Button(gpio_num_t gpioNum) { mGPIONum = gpioNum; } int32_t Find_Button_Via_Pin(gpio_num_t gpioNum) { for (int i = 0; i < BUTTON_NUMBER; i++) { if (gButtons[i].GetGPIONum() == gpioNum) { return i; } } return -1; } void IRAM_ATTR button_isr_handler(void * arg) { uint32_t gpio_num = (uint32_t) arg; int32_t idx = Find_Button_Via_Pin((gpio_num_t) gpio_num); if (idx == -1) { return; } BaseType_t taskWoken = pdFALSE; xTimerStartFromISR(gButtons[idx].mbuttonTimer, &taskWoken); // If the timer had already been started ,restart it will reset its expiry time } esp_err_t Button::Init() { return Init(mGPIONum); } esp_err_t Button::Init(gpio_num_t gpioNum) { esp_err_t ret = ESP_OK; mGPIONum = gpioNum; // zero-initialize the config structure. gpio_config_t io_conf = {}; // interrupt of falling edge io_conf.intr_type = GPIO_INTR_NEGEDGE; // bit mask of the pins, use GPIO4/5 here io_conf.pin_bit_mask = 1ULL << gpioNum; // set as input mode io_conf.mode = GPIO_MODE_INPUT; // enable pull-up mode io_conf.pull_up_en = GPIO_PULLUP_ENABLE; gpio_config(&io_conf); // hook isr handler for specific gpio pin ret = gpio_isr_handler_add(gpioNum, button_isr_handler, (void *) gpioNum); ESP_RETURN_ON_ERROR(ret, TAG, "gpio_isr_handler_add failed: %s", esp_err_to_name(ret)); mbuttonTimer = xTimerCreate("BtnTmr", // Just a text name, not used by the RTOS kernel pdMS_TO_TICKS(50), // timer period false, // no timer reload (==one-shot) (void *) (int) gpioNum, // init timer id = gpioNum index TimerCallback // timer callback handler (all buttons use // the same timer cn function) ); return ESP_OK; } void Button::TimerCallback(TimerHandle_t xTimer) { // Get the button index of the expired timer and call button event Handler. uint32_t gpio_num = (uint32_t) pvTimerGetTimerID(xTimer); GetAppTask().ButtonEventHandler(gpio_num, APP_BUTTON_PRESSED); }