| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /*
- * Copyright (c) 2021 Espressif Systems (Shanghai) CO LTD
- * All rights reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Espressif Systems
- * integrated circuit in a product or a software update for such product,
- * must reproduce the above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * 4. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include "esp_log.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/queue.h"
- #include "switch_driver.h"
- /**
- * @brief:
- * This example code shows how to configure light switch with attribute as well as button switch handler.
- *
- * @note:
- Currently only support toggle switch functionality available
- *
- * @note:
- * For other possible switch functions (on/off,level up/down,step up/down). User need to implement and create them by themselves
- */
- static QueueHandle_t gpio_evt_queue = NULL;
- /* button function pair, should be defined in switch example source file */
- static switch_func_pair_t *switch_func_pair;
- /* call back function pointer */
- static esp_switch_callback_t func_ptr;
- /* which button is pressed */
- static uint8_t switch_num;
- static const char *TAG = "ESP_ZB_SWITCH";
- static void IRAM_ATTR gpio_isr_handler(void *arg)
- {
- xQueueSendFromISR(gpio_evt_queue, (switch_func_pair_t *)arg, NULL);
- }
- /**
- * @brief Enable GPIO (switchs refer to) isr
- *
- * @param enabled enable isr if true.
- */
- static void switch_driver_gpios_intr_enabled(bool enabled)
- {
- for (int i = 0; i < switch_num; ++i) {
- if (enabled) {
- gpio_intr_enable((switch_func_pair + i)->pin);
- } else {
- gpio_intr_disable((switch_func_pair + i)->pin);
- }
- }
- }
- /**
- * @brief Tasks for checking the button event and debounce the switch state
- *
- * @param arg Unused value.
- */
- static void switch_driver_button_detected(void *arg)
- {
- gpio_num_t io_num = GPIO_NUM_NC;
- switch_func_pair_t button_func_pair;
- static switch_state_t switch_state = SWITCH_IDLE;
- bool evt_flag = false;
- for (;;) {
- /* check if there is any queue received, if yes read out the button_func_pair */
- if (xQueueReceive(gpio_evt_queue, &button_func_pair, portMAX_DELAY)) {
- io_num = button_func_pair.pin;
- switch_driver_gpios_intr_enabled(false);
- evt_flag = true;
- }
- while (evt_flag) {
- bool value = gpio_get_level(io_num);
- switch (switch_state) {
- case SWITCH_IDLE:
- switch_state = (value == GPIO_INPUT_LEVEL_ON) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE;
- break;
- case SWITCH_PRESS_DETECTED:
- switch_state = (value == GPIO_INPUT_LEVEL_ON) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED;
- break;
- case SWITCH_RELEASE_DETECTED:
- switch_state = SWITCH_IDLE;
- /* callback to button_handler */
- (*func_ptr)(button_func_pair);
- break;
- default:
- break;
- }
- if (switch_state == SWITCH_IDLE) {
- switch_driver_gpios_intr_enabled(true);
- evt_flag = false;
- break;
- }
- vTaskDelay(10 / portTICK_PERIOD_MS);
- }
- }
- }
- /**
- * @brief init GPIO configuration as well as isr
- *
- * @param button_func_pair pointer of the button pair.
- * @param button_num number of button pair.
- */
- static bool switch_driver_gpio_init(switch_func_pair_t *button_func_pair, uint8_t button_num)
- {
- gpio_config_t io_conf = {};
- switch_func_pair = button_func_pair;
- switch_num = button_num;
- uint64_t pin_bit_mask = 0;
- /* set up button func pair pin mask */
- for (int i = 0; i < button_num; ++i) {
- pin_bit_mask |= (1ULL << (button_func_pair + i)->pin);
- }
- /* interrupt of falling edge */
- io_conf.intr_type = GPIO_INTR_NEGEDGE;
- io_conf.pin_bit_mask = pin_bit_mask;
- io_conf.mode = GPIO_MODE_INPUT;
- io_conf.pull_up_en = 1;
- /* configure GPIO with the given settings */
- gpio_config(&io_conf);
- /* create a queue to handle gpio event from isr */
- gpio_evt_queue = xQueueCreate(10, sizeof(switch_func_pair_t));
- if ( gpio_evt_queue == 0) {
- ESP_LOGE(TAG, "Queue was not created and must not be used");
- return false;
- }
- /* start gpio task */
- xTaskCreate(switch_driver_button_detected, "button_detected", 2048, NULL, 10, NULL);
- /* install gpio isr service */
- gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
- for (int i = 0; i < button_num; ++i) {
- gpio_isr_handler_add((button_func_pair + i)->pin, gpio_isr_handler, (void *) (button_func_pair + i));
- }
- return true;
- }
- bool switch_driver_init(switch_func_pair_t *button_func_pair, uint8_t button_num, esp_switch_callback_t cb)
- {
- if (!switch_driver_gpio_init(button_func_pair, button_num)) {
- return false;
- }
- func_ptr = cb;
- return true;
- }
|