esp-who/components/modules/button/who_button.c

100 lines
2.4 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include "who_button.h"
typedef struct
{
gpio_num_t io_num;
key_state_t state;
} key_scan_state_t;
#define LONG_PRESS_THRESH 700000
#define DOUBLE_CLICK_THRESH 300000
static xQueueHandle gpio_evt_queue = NULL;
static QueueHandle_t xQueueKeyStateO = NULL;
static void IRAM_ATTR gpio_isr_handler_key(void *arg)
{
uint32_t gpio_num = (uint32_t)arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
int key_scan(TickType_t ticks_to_wait)
{
gpio_num_t io_num;
BaseType_t press_key = pdFALSE;
BaseType_t lift_key = pdFALSE;
int64_t backup_time = 0;
int64_t interval_time = 0;
static int64_t last_time = 0;
for (;;)
{
xQueueReceive(gpio_evt_queue, &io_num, ticks_to_wait);
if (gpio_get_level(io_num) == 0)
{
press_key = pdTRUE;
backup_time = esp_timer_get_time();
interval_time = backup_time - last_time;
}
else if (press_key)
{
lift_key = pdTRUE;
last_time = esp_timer_get_time();
backup_time = last_time - backup_time;
}
if (press_key & lift_key)
{
press_key = pdFALSE;
lift_key = pdFALSE;
if (backup_time > LONG_PRESS_THRESH)
{
return KEY_LONG_PRESS;
}
else
{
if ((interval_time < DOUBLE_CLICK_THRESH) && (interval_time > 0))
return KEY_DOUBLE_CLICK;
else
return KEY_SHORT_PRESS;
}
}
}
}
void key_trigger(void *arg)
{
int ret = 0;
while (1)
{
ret = key_scan(portMAX_DELAY);
xQueueOverwrite(xQueueKeyStateO, &ret);
}
vTaskDelete(NULL);
}
void key_init(gpio_num_t gpio_num)
{
gpio_config_t io_conf = {0};
io_conf.mode = GPIO_MODE_INPUT;
io_conf.intr_type = GPIO_INTR_ANYEDGE;
io_conf.pin_bit_mask = 1LL << gpio_num;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
gpio_evt_queue = xQueueCreate(5, sizeof(uint32_t));
gpio_install_isr_service(0);
gpio_isr_handler_add(gpio_num, gpio_isr_handler_key, (void *)gpio_num);
}
void register_button(const gpio_num_t key_io_num, const QueueHandle_t key_state_o)
{
xQueueKeyStateO = key_state_o;
key_init(key_io_num);
xTaskCreatePinnedToCore(key_trigger, "key_scan_task", 1024, NULL, 5, NULL, 0);
}