mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-19 09:25:54 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "button_adc.c" "button_gpio.c" "iot_button.c"
|
||||
INCLUDE_DIRS include
|
||||
PRIV_REQUIRES esp_adc_cal)
|
||||
@@ -0,0 +1,46 @@
|
||||
menu "IoT Button"
|
||||
|
||||
config BUTTON_PERIOD_TIME_MS
|
||||
int "BUTTON PERIOD TIME (MS)"
|
||||
range 2 20
|
||||
default 5
|
||||
help
|
||||
"Button scan interval"
|
||||
|
||||
config BUTTON_DEBOUNCE_TICKS
|
||||
int "BUTTON DEBOUNCE TICKS"
|
||||
range 1 8
|
||||
default 2
|
||||
|
||||
config BUTTON_SHORT_PRESS_TIME_MS
|
||||
int "BUTTON SHORT PRESS TIME (MS)"
|
||||
range 50 800
|
||||
default 180
|
||||
|
||||
config BUTTON_LONG_PRESS_TIME_MS
|
||||
int "BUTTON LONG PRESS TIME (MS)"
|
||||
range 500 5000
|
||||
default 1500
|
||||
|
||||
config ADC_BUTTON_MAX_CHANNEL
|
||||
int "ADC BUTTON MAX CHANNEL"
|
||||
range 1 5
|
||||
default 3
|
||||
help
|
||||
"Maximum number of channels for ADC buttons"
|
||||
|
||||
config ADC_BUTTON_MAX_BUTTON_PER_CHANNEL
|
||||
int "ADC BUTTON MAX BUTTON PER CHANNEL"
|
||||
range 1 10
|
||||
default 8
|
||||
help
|
||||
"Maximum number of buttons per channel"
|
||||
|
||||
config ADC_BUTTON_SAMPLE_TIMES
|
||||
int "ADC BUTTON SAMPLE TIMES"
|
||||
range 1 4
|
||||
default 1
|
||||
help
|
||||
"Number of samples per scan"
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,208 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
#include "esp_adc_cal.h"
|
||||
#include "button_adc.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
static const char *TAG = "adc button";
|
||||
|
||||
#define ADC_BTN_CHECK(a, str, ret_val) \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
}
|
||||
|
||||
#define DEFAULT_VREF 1100
|
||||
#define NO_OF_SAMPLES CONFIG_ADC_BUTTON_SAMPLE_TIMES //Multisampling
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define ADC_BUTTON_WIDTH ADC_WIDTH_BIT_12
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define ADC_BUTTON_WIDTH ADC_WIDTH_BIT_13
|
||||
#endif
|
||||
#define ADC_BUTTON_ATTEN ADC_ATTEN_DB_11
|
||||
#define ADC_BUTTON_ADC_UNIT ADC_UNIT_1
|
||||
#define ADC_BUTTON_MAX_CHANNEL CONFIG_ADC_BUTTON_MAX_CHANNEL
|
||||
#define ADC_BUTTON_MAX_BUTTON CONFIG_ADC_BUTTON_MAX_BUTTON_PER_CHANNEL
|
||||
|
||||
typedef struct {
|
||||
uint16_t min;
|
||||
uint16_t max;
|
||||
} button_data_t;
|
||||
|
||||
typedef struct {
|
||||
adc1_channel_t channel;
|
||||
uint8_t is_init;
|
||||
button_data_t btns[ADC_BUTTON_MAX_BUTTON]; /* all button on the channel */
|
||||
uint64_t last_time; /* the last time of adc sample */
|
||||
} btn_adc_channel_t;
|
||||
|
||||
typedef struct {
|
||||
bool is_configured;
|
||||
esp_adc_cal_characteristics_t adc_chars;
|
||||
btn_adc_channel_t ch[ADC_BUTTON_MAX_CHANNEL];
|
||||
uint8_t ch_num;
|
||||
} adc_button_t;
|
||||
|
||||
static adc_button_t g_button = {0};
|
||||
|
||||
static int find_unused_channel(void)
|
||||
{
|
||||
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
||||
if (0 == g_button.ch[i].is_init) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_channel(adc1_channel_t channel)
|
||||
{
|
||||
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
||||
if (channel == g_button.ch[i].channel) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
esp_err_t button_adc_init(const button_adc_config_t *config)
|
||||
{
|
||||
ADC_BTN_CHECK(NULL != config, "Pointer of config is invalid", ESP_ERR_INVALID_ARG);
|
||||
ADC_BTN_CHECK(config->adc_channel < ADC1_CHANNEL_MAX, "channel out of range", ESP_ERR_NOT_SUPPORTED);
|
||||
ADC_BTN_CHECK(config->button_index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", ESP_ERR_NOT_SUPPORTED);
|
||||
ADC_BTN_CHECK(config->max > 0, "key max voltage invalid", ESP_ERR_INVALID_ARG);
|
||||
|
||||
int ch_index = find_channel(config->adc_channel);
|
||||
if (ch_index >= 0) { /**< the channel has been initialized */
|
||||
ADC_BTN_CHECK(g_button.ch[ch_index].btns[config->button_index].max == 0, "The button_index has been used", ESP_ERR_INVALID_STATE);
|
||||
} else { /**< this is a new channel */
|
||||
int unused_ch_index = find_unused_channel();
|
||||
ADC_BTN_CHECK(unused_ch_index >= 0, "exceed max channel number, can't create a new channel", ESP_ERR_INVALID_STATE);
|
||||
ch_index = unused_ch_index;
|
||||
}
|
||||
|
||||
/** initialize adc */
|
||||
if (0 == g_button.is_configured) {
|
||||
//Configure ADC
|
||||
adc1_config_width(ADC_BUTTON_WIDTH);
|
||||
//Characterize ADC
|
||||
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_BUTTON_ADC_UNIT, ADC_BUTTON_ATTEN, ADC_BUTTON_WIDTH, DEFAULT_VREF, &g_button.adc_chars);
|
||||
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
|
||||
ESP_LOGI(TAG, "Characterized using Two Point Value");
|
||||
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
|
||||
ESP_LOGI(TAG, "Characterized using eFuse Vref");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Characterized using Default Vref");
|
||||
}
|
||||
g_button.is_configured = 1;
|
||||
}
|
||||
|
||||
/** initialize adc channel */
|
||||
if (0 == g_button.ch[ch_index].is_init) {
|
||||
adc1_config_channel_atten(config->adc_channel, ADC_BUTTON_ATTEN);
|
||||
g_button.ch[ch_index].channel = config->adc_channel;
|
||||
g_button.ch[ch_index].is_init = 1;
|
||||
g_button.ch[ch_index].last_time = 0;
|
||||
}
|
||||
g_button.ch[ch_index].btns[config->button_index].max = config->max;
|
||||
g_button.ch[ch_index].btns[config->button_index].min = config->min;
|
||||
g_button.ch_num++;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t button_adc_deinit(adc1_channel_t channel, int button_index)
|
||||
{
|
||||
ADC_BTN_CHECK(channel < ADC1_CHANNEL_MAX, "channel out of range", ESP_ERR_INVALID_ARG);
|
||||
ADC_BTN_CHECK(button_index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", ESP_ERR_INVALID_ARG);
|
||||
|
||||
int ch_index = find_channel(channel);
|
||||
ADC_BTN_CHECK(ch_index >= 0, "can't find the channel", ESP_ERR_INVALID_ARG);
|
||||
|
||||
g_button.ch[ch_index].btns[button_index].max = 0;
|
||||
g_button.ch[ch_index].btns[button_index].min = 0;
|
||||
|
||||
/** check button usage on the channel*/
|
||||
uint8_t unused_button = 0;
|
||||
for (size_t i = 0; i < ADC_BUTTON_MAX_BUTTON; i++) {
|
||||
if (0 == g_button.ch[ch_index].btns[i].max) {
|
||||
unused_button++;
|
||||
}
|
||||
}
|
||||
if (unused_button == ADC_BUTTON_MAX_BUTTON && g_button.ch[ch_index].is_init) { /**< if all button is unused, deinit the channel */
|
||||
/* TODO: to deinit the channel */
|
||||
g_button.ch[ch_index].is_init = 0;
|
||||
g_button.ch[ch_index].channel = ADC1_CHANNEL_MAX;
|
||||
ESP_LOGD(TAG, "all button is unused on channel%d, deinit the channel", g_button.ch[ch_index].channel);
|
||||
}
|
||||
|
||||
/** check channel usage on the adc*/
|
||||
uint8_t unused_ch = 0;
|
||||
for (size_t i = 0; i < ADC_BUTTON_MAX_CHANNEL; i++) {
|
||||
if (0 == g_button.ch[i].is_init) {
|
||||
unused_ch++;
|
||||
}
|
||||
}
|
||||
if (unused_ch == ADC_BUTTON_MAX_CHANNEL && g_button.is_configured) { /**< if all channel is unused, deinit the adc */
|
||||
/* TODO: to deinit the peripheral adc */
|
||||
g_button.is_configured = false;
|
||||
memset(&g_button, 0, sizeof(adc_button_t));
|
||||
ESP_LOGD(TAG, "all channel is unused, , deinit adc");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint32_t get_adc_volatge(adc1_channel_t channel)
|
||||
{
|
||||
uint32_t adc_reading = 0;
|
||||
//Multisampling
|
||||
for (int i = 0; i < NO_OF_SAMPLES; i++) {
|
||||
adc_reading += adc1_get_raw(channel);
|
||||
}
|
||||
adc_reading /= NO_OF_SAMPLES;
|
||||
//Convert adc_reading to voltage in mV
|
||||
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, &g_button.adc_chars);
|
||||
ESP_LOGV(TAG, "Raw: %d\tVoltage: %dmV", adc_reading, voltage);
|
||||
return voltage;
|
||||
}
|
||||
|
||||
uint8_t button_adc_get_key_level(void *button_index)
|
||||
{
|
||||
static uint16_t vol = 0;
|
||||
uint32_t ch = ADC_BUTTON_SPLIT_CHANNEL(button_index);
|
||||
uint32_t index = ADC_BUTTON_SPLIT_INDEX(button_index);
|
||||
ADC_BTN_CHECK(ch < ADC1_CHANNEL_MAX, "channel out of range", 0);
|
||||
ADC_BTN_CHECK(index < ADC_BUTTON_MAX_BUTTON, "button_index out of range", 0);
|
||||
int ch_index = find_channel(ch);
|
||||
ADC_BTN_CHECK(ch_index >= 0, "The button_index is not init", 0);
|
||||
|
||||
/** It starts only when the elapsed time is more than 1ms */
|
||||
if ((esp_timer_get_time() - g_button.ch[ch_index].last_time) > 1000) {
|
||||
vol = get_adc_volatge(ch);
|
||||
g_button.ch[ch_index].last_time = esp_timer_get_time();
|
||||
}
|
||||
|
||||
if (vol <= g_button.ch[ch_index].btns[index].max &&
|
||||
vol > g_button.ch[ch_index].btns[index].min) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "button_gpio.h"
|
||||
|
||||
static const char *TAG = "gpio button";
|
||||
|
||||
#define GPIO_BTN_CHECK(a, str, ret_val) \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
}
|
||||
|
||||
esp_err_t button_gpio_init(const button_gpio_config_t *config)
|
||||
{
|
||||
GPIO_BTN_CHECK(NULL != config, "Pointer of config is invalid", ESP_ERR_INVALID_ARG);
|
||||
|
||||
gpio_config_t gpio_conf;
|
||||
gpio_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_conf.mode = GPIO_MODE_INPUT;
|
||||
gpio_conf.pin_bit_mask = (1ULL << config->gpio_num);
|
||||
if (config->active_level) {
|
||||
gpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
|
||||
gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
} else {
|
||||
gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
}
|
||||
gpio_config(&gpio_conf);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t button_gpio_deinit(int gpio_num)
|
||||
{
|
||||
/** both disable pullup and pulldown */
|
||||
gpio_config_t gpio_conf = {
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pin_bit_mask = (1ULL << gpio_num),
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
};
|
||||
gpio_config(&gpio_conf);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint8_t button_gpio_get_key_level(void *gpio_num)
|
||||
{
|
||||
return (uint8_t)gpio_get_level((uint32_t)gpio_num);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := ./include
|
||||
COMPONENT_SRCDIRS := .
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
#ifndef _IOT_BUTTON_ADC_H_
|
||||
#define _IOT_BUTTON_ADC_H_
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ADC_BUTTON_COMBINE(channel, index) ((channel)<<8 | (index))
|
||||
#define ADC_BUTTON_SPLIT_INDEX(data) ((uint32_t)(data)&0xff)
|
||||
#define ADC_BUTTON_SPLIT_CHANNEL(data) (((uint32_t)(data) >> 8) & 0xff)
|
||||
|
||||
/**
|
||||
* @brief adc button configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
adc1_channel_t adc_channel; /**< Channel of ADC */
|
||||
uint8_t button_index; /**< button index on the channel */
|
||||
uint16_t min; /**< min voltage in mv corresponding to the button */
|
||||
uint16_t max; /**< max voltage in mv corresponding to the button */
|
||||
} button_adc_config_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize gpio button
|
||||
*
|
||||
* @param config pointer of configuration struct
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG Arguments is NULL.
|
||||
* - ESP_ERR_NOT_SUPPORTED Arguments out of range.
|
||||
* - ESP_ERR_INVALID_STATE State is error.
|
||||
*/
|
||||
esp_err_t button_adc_init(const button_adc_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize gpio button
|
||||
*
|
||||
* @param channel ADC channel
|
||||
* @param button_index Button index on the channel
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
||||
*/
|
||||
esp_err_t button_adc_deinit(adc1_channel_t channel, int button_index);
|
||||
|
||||
/**
|
||||
* @brief Get the adc button level
|
||||
*
|
||||
* @param button_index It is compressed by ADC channel and button index, use the macro ADC_BUTTON_COMBINE to generate. It will be treated as a uint32_t variable.
|
||||
*
|
||||
* @return
|
||||
* - 0 Not pressed
|
||||
* - 1 Pressed
|
||||
*/
|
||||
uint8_t button_adc_get_key_level(void *button_index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
#ifndef _IOT_BUTTON_GPIO_H_
|
||||
#define _IOT_BUTTON_GPIO_H_
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief gpio button configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
int32_t gpio_num;
|
||||
uint8_t active_level;
|
||||
} button_gpio_config_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize gpio button
|
||||
*
|
||||
* @param config pointer of configuration struct
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG Arguments is NULL.
|
||||
*/
|
||||
esp_err_t button_gpio_init(const button_gpio_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize gpio button
|
||||
*
|
||||
* @param gpio_num gpio number of button
|
||||
*
|
||||
* @return Always return ESP_OK
|
||||
*/
|
||||
esp_err_t button_gpio_deinit(int gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Get current level on button gpio
|
||||
*
|
||||
* @param gpio_num gpio number of button, it will be treated as a uint32_t variable.
|
||||
*
|
||||
* @return Level on gpio
|
||||
*/
|
||||
uint8_t button_gpio_get_key_level(void *gpio_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
#ifndef _IOT_BUTTON_H_
|
||||
#define _IOT_BUTTON_H_
|
||||
|
||||
#include "button_adc.h"
|
||||
#include "button_gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (* button_cb_t)(void *);
|
||||
typedef void *button_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Button events
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
BUTTON_PRESS_DOWN = 0,
|
||||
BUTTON_PRESS_UP,
|
||||
BUTTON_PRESS_REPEAT,
|
||||
BUTTON_SINGLE_CLICK,
|
||||
BUTTON_DOUBLE_CLICK,
|
||||
BUTTON_LONG_PRESS_START,
|
||||
BUTTON_LONG_PRESS_HOLD,
|
||||
BUTTON_EVENT_MAX,
|
||||
BUTTON_NONE_PRESS,
|
||||
} button_event_t;
|
||||
|
||||
/**
|
||||
* @brief Supported button type
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
BUTTON_TYPE_GPIO,
|
||||
BUTTON_TYPE_ADC,
|
||||
} button_type_t;
|
||||
|
||||
/**
|
||||
* @brief Button configuration
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
button_type_t type; /**< button type, The corresponding button configuration must be filled */
|
||||
union {
|
||||
button_gpio_config_t gpio_button_config; /**< gpio button configuration */
|
||||
button_adc_config_t adc_button_config; /**< adc button configuration */
|
||||
}; /**< button configuration */
|
||||
} button_config_t;
|
||||
|
||||
/**
|
||||
* @brief Create a button
|
||||
*
|
||||
* @param config pointer of button configuration, must corresponding the button type
|
||||
*
|
||||
* @return A handle to the created button, or NULL in case of error.
|
||||
*/
|
||||
button_handle_t iot_button_create(const button_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Delete a button
|
||||
*
|
||||
* @param btn_handle A button handle to delete
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Failure
|
||||
*/
|
||||
esp_err_t iot_button_delete(button_handle_t btn_handle);
|
||||
|
||||
/**
|
||||
* @brief Register the button event callback function.
|
||||
*
|
||||
* @param btn_handle A button handle to register
|
||||
* @param event Button event
|
||||
* @param cb Callback function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
||||
*/
|
||||
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb);
|
||||
|
||||
/**
|
||||
* @brief Unregister the button event callback function.
|
||||
*
|
||||
* @param btn_handle A button handle to unregister
|
||||
* @param event Button event
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG Arguments is invalid.
|
||||
*/
|
||||
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event);
|
||||
|
||||
/**
|
||||
* @brief Get button event
|
||||
*
|
||||
* @param btn_handle Button handle
|
||||
*
|
||||
* @return Current button event. See button_event_t
|
||||
*/
|
||||
button_event_t iot_button_get_event(button_handle_t btn_handle);
|
||||
|
||||
/**
|
||||
* @brief Get button repeat times
|
||||
*
|
||||
* @param btn_handle Button handle
|
||||
*
|
||||
* @return button pressed times. For example, double-click return 2, triple-click return 3, etc.
|
||||
*/
|
||||
uint8_t iot_button_get_repeat(button_handle_t btn_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,306 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "iot_button.h"
|
||||
#include "esp_timer.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char *TAG = "button";
|
||||
|
||||
#define BTN_CHECK(a, str, ret_val) \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
|
||||
return (ret_val); \
|
||||
}
|
||||
|
||||
typedef struct Button {
|
||||
uint16_t ticks;
|
||||
uint8_t repeat;
|
||||
button_event_t event;
|
||||
uint8_t state: 3;
|
||||
uint8_t debounce_cnt: 3;
|
||||
uint8_t active_level: 1;
|
||||
uint8_t button_level: 1;
|
||||
uint8_t (*hal_button_Level)(void *usr_data);
|
||||
void *usr_data;
|
||||
button_type_t type;
|
||||
button_cb_t cb[BUTTON_EVENT_MAX];
|
||||
struct Button *next;
|
||||
} button_dev_t;
|
||||
|
||||
//button handle list head.
|
||||
static button_dev_t *g_head_handle = NULL;
|
||||
static esp_timer_handle_t g_button_timer_handle;
|
||||
static bool g_is_timer_running = false;
|
||||
|
||||
#define TICKS_INTERVAL CONFIG_BUTTON_PERIOD_TIME_MS
|
||||
#define DEBOUNCE_TICKS CONFIG_BUTTON_DEBOUNCE_TICKS //MAX 8
|
||||
#define SHORT_TICKS (CONFIG_BUTTON_SHORT_PRESS_TIME_MS /TICKS_INTERVAL)
|
||||
#define LONG_TICKS (CONFIG_BUTTON_LONG_PRESS_TIME_MS /TICKS_INTERVAL)
|
||||
|
||||
#define CALL_EVENT_CB(ev) if(btn->cb[ev])btn->cb[ev](btn)
|
||||
|
||||
/**
|
||||
* @brief Button driver core function, driver state machine.
|
||||
*/
|
||||
static void button_handler(button_dev_t *btn)
|
||||
{
|
||||
uint8_t read_gpio_level = btn->hal_button_Level(btn->usr_data);
|
||||
|
||||
/** ticks counter working.. */
|
||||
if ((btn->state) > 0) {
|
||||
btn->ticks++;
|
||||
}
|
||||
|
||||
/**< button debounce handle */
|
||||
if (read_gpio_level != btn->button_level) {
|
||||
if (++(btn->debounce_cnt) >= DEBOUNCE_TICKS) {
|
||||
btn->button_level = read_gpio_level;
|
||||
btn->debounce_cnt = 0;
|
||||
}
|
||||
} else {
|
||||
btn->debounce_cnt = 0;
|
||||
}
|
||||
|
||||
/** State machine */
|
||||
switch (btn->state) {
|
||||
case 0:
|
||||
if (btn->button_level == btn->active_level) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
||||
btn->ticks = 0;
|
||||
btn->repeat = 1;
|
||||
btn->state = 1;
|
||||
} else {
|
||||
btn->event = (uint8_t)BUTTON_NONE_PRESS;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (btn->button_level != btn->active_level) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||
btn->ticks = 0;
|
||||
btn->state = 2;
|
||||
|
||||
} else if (btn->ticks > LONG_TICKS) {
|
||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
||||
CALL_EVENT_CB(BUTTON_LONG_PRESS_START);
|
||||
btn->state = 5;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (btn->button_level == btn->active_level) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
||||
btn->repeat++;
|
||||
// CALL_EVENT_CB(BUTTON_PRESS_REPEAT); // repeat hit
|
||||
btn->ticks = 0;
|
||||
btn->state = 3;
|
||||
} else if (btn->ticks > SHORT_TICKS) {
|
||||
if (btn->repeat == 1) {
|
||||
btn->event = (uint8_t)BUTTON_SINGLE_CLICK;
|
||||
CALL_EVENT_CB(BUTTON_SINGLE_CLICK);
|
||||
}
|
||||
// else if (btn->repeat == 2) {
|
||||
// btn->event = (uint8_t)BUTTON_DOUBLE_CLICK;
|
||||
// CALL_EVENT_CB(BUTTON_DOUBLE_CLICK); // repeat hit
|
||||
// ESP_LOGE(TAG, "003:double click");
|
||||
// }
|
||||
else {
|
||||
CALL_EVENT_CB(BUTTON_PRESS_REPEAT); // repeat hit
|
||||
}
|
||||
btn->state = 0;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (btn->button_level != btn->active_level) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||
if (btn->ticks < SHORT_TICKS) {
|
||||
btn->ticks = 0;
|
||||
btn->state = 2; //repeat press
|
||||
} else {
|
||||
btn->state = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (btn->button_level == btn->active_level) {
|
||||
//continue hold trigger
|
||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_HOLD;
|
||||
CALL_EVENT_CB(BUTTON_LONG_PRESS_HOLD);
|
||||
} else { //releasd
|
||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||
btn->state = 0; //reset
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void button_cb(void *args)
|
||||
{
|
||||
button_dev_t *target;
|
||||
for (target = g_head_handle; target; target = target->next) {
|
||||
button_handler(target);
|
||||
}
|
||||
}
|
||||
|
||||
static button_dev_t *button_create_com(uint8_t active_level, uint8_t (*hal_get_key_state)(void *usr_data), void *usr_data)
|
||||
{
|
||||
BTN_CHECK(NULL != hal_get_key_state, "Function pointer is invalid", NULL);
|
||||
|
||||
button_dev_t *btn = (button_dev_t *) calloc(1, sizeof(button_dev_t));
|
||||
BTN_CHECK(NULL != btn, "Button memory alloc failed", NULL);
|
||||
btn->usr_data = usr_data;
|
||||
btn->event = BUTTON_NONE_PRESS;
|
||||
btn->active_level = active_level;
|
||||
btn->hal_button_Level = hal_get_key_state;
|
||||
btn->button_level = !active_level;
|
||||
|
||||
/** Add handle to list */
|
||||
btn->next = g_head_handle;
|
||||
g_head_handle = btn;
|
||||
|
||||
if (false == g_is_timer_running) {
|
||||
esp_timer_create_args_t button_timer;
|
||||
button_timer.arg = NULL;
|
||||
button_timer.callback = button_cb;
|
||||
button_timer.dispatch_method = ESP_TIMER_TASK;
|
||||
button_timer.name = "button_timer";
|
||||
esp_timer_create(&button_timer, &g_button_timer_handle);
|
||||
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||
g_is_timer_running = true;
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
static esp_err_t button_delete_com(button_dev_t *btn)
|
||||
{
|
||||
BTN_CHECK(NULL != btn, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
|
||||
button_dev_t **curr;
|
||||
for (curr = &g_head_handle; *curr; ) {
|
||||
button_dev_t *entry = *curr;
|
||||
if (entry == btn) {
|
||||
*curr = entry->next;
|
||||
free(entry);
|
||||
} else {
|
||||
curr = &entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* count button number */
|
||||
uint16_t number = 0;
|
||||
button_dev_t *target = g_head_handle;
|
||||
while (target) {
|
||||
target = target->next;
|
||||
number++;
|
||||
}
|
||||
ESP_LOGD(TAG, "remain btn number=%d", number);
|
||||
|
||||
if (0 == number && g_is_timer_running) { /**< if all button is deleted, stop the timer */
|
||||
esp_timer_stop(g_button_timer_handle);
|
||||
esp_timer_delete(g_button_timer_handle);
|
||||
g_is_timer_running = false;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
button_handle_t iot_button_create(const button_config_t *config)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
button_dev_t *btn = NULL;
|
||||
switch (config->type) {
|
||||
case BUTTON_TYPE_GPIO: {
|
||||
const button_gpio_config_t *cfg = &(config->gpio_button_config);
|
||||
ret = button_gpio_init(cfg);
|
||||
BTN_CHECK(ESP_OK == ret, "gpio button init failed", NULL);
|
||||
btn = button_create_com(cfg->active_level, button_gpio_get_key_level, (void *)cfg->gpio_num);
|
||||
} break;
|
||||
case BUTTON_TYPE_ADC: {
|
||||
const button_adc_config_t *cfg = &(config->adc_button_config);
|
||||
ret = button_adc_init(cfg);
|
||||
BTN_CHECK(ESP_OK == ret, "adc button init failed", NULL);
|
||||
btn = button_create_com(1, button_adc_get_key_level, (void *)ADC_BUTTON_COMBINE(cfg->adc_channel, cfg->button_index));
|
||||
} break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unsupported button type");
|
||||
break;
|
||||
}
|
||||
BTN_CHECK(NULL != btn, "button create failed", NULL);
|
||||
btn->type = config->type;
|
||||
return (button_handle_t)btn;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_delete(button_handle_t btn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_dev_t *btn = (button_dev_t *)btn_handle;
|
||||
switch (btn->type) {
|
||||
case BUTTON_TYPE_GPIO:
|
||||
ret = button_gpio_deinit((int)(btn->usr_data));
|
||||
break;
|
||||
case BUTTON_TYPE_ADC:
|
||||
ret = button_adc_deinit(ADC_BUTTON_SPLIT_CHANNEL(btn->usr_data), ADC_BUTTON_SPLIT_INDEX(btn->usr_data));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BTN_CHECK(ESP_OK == ret, "button deinit failed", ESP_FAIL);
|
||||
button_delete_com(btn);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
btn->cb[event] = cb;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
btn->cb[event] = NULL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
button_event_t iot_button_get_event(button_handle_t btn_handle)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", BUTTON_NONE_PRESS);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
return btn->event;
|
||||
}
|
||||
|
||||
uint8_t iot_button_get_repeat(button_handle_t btn_handle)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
return btn->repeat;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES unity test_utils button)
|
||||
@@ -0,0 +1,234 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include "stdio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_log.h"
|
||||
#include "unity.h"
|
||||
#include "iot_button.h"
|
||||
|
||||
static const char *TAG = "BUTTON TEST";
|
||||
|
||||
#define BUTTON_IO_NUM 0
|
||||
#define BUTTON_ACTIVE_LEVEL 0
|
||||
#define BUTTON_NUM 16
|
||||
|
||||
static button_handle_t g_btns[BUTTON_NUM] = {0};
|
||||
|
||||
static int get_btn_index(button_handle_t btn)
|
||||
{
|
||||
for (size_t i = 0; i < BUTTON_NUM; i++) {
|
||||
if (btn == g_btns[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void button_press_down_cb(void *arg)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_HEX(BUTTON_PRESS_DOWN, iot_button_get_event(arg));
|
||||
ESP_LOGI(TAG, "BTN%d: BUTTON_PRESS_DOWN", get_btn_index((button_handle_t)arg));
|
||||
}
|
||||
|
||||
static void button_press_up_cb(void *arg)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_HEX(BUTTON_PRESS_UP, iot_button_get_event(arg));
|
||||
ESP_LOGI(TAG, "BTN%d: BUTTON_PRESS_UP", get_btn_index((button_handle_t)arg));
|
||||
}
|
||||
|
||||
static void button_press_repeat_cb(void *arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "BTN%d: BUTTON_PRESS_REPEAT[%d]", get_btn_index((button_handle_t)arg), iot_button_get_repeat((button_handle_t)arg));
|
||||
}
|
||||
|
||||
static void button_single_click_cb(void *arg)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_HEX(BUTTON_SINGLE_CLICK, iot_button_get_event(arg));
|
||||
ESP_LOGI(TAG, "BTN%d: BUTTON_SINGLE_CLICK", get_btn_index((button_handle_t)arg));
|
||||
}
|
||||
|
||||
static void button_double_click_cb(void *arg)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_HEX(BUTTON_DOUBLE_CLICK, iot_button_get_event(arg));
|
||||
ESP_LOGI(TAG, "BTN%d: BUTTON_DOUBLE_CLICK", get_btn_index((button_handle_t)arg));
|
||||
}
|
||||
|
||||
static void button_long_press_start_cb(void *arg)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_HEX(BUTTON_LONG_PRESS_START, iot_button_get_event(arg));
|
||||
ESP_LOGI(TAG, "BTN%d: BUTTON_LONG_PRESS_START", get_btn_index((button_handle_t)arg));
|
||||
}
|
||||
|
||||
static void button_long_press_hold_cb(void *arg)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_HEX(BUTTON_LONG_PRESS_HOLD, iot_button_get_event(arg));
|
||||
ESP_LOGI(TAG, "BTN%d: BUTTON_LONG_PRESS_HOLD", get_btn_index((button_handle_t)arg));
|
||||
}
|
||||
|
||||
static void print_button_event(button_handle_t btn)
|
||||
{
|
||||
button_event_t evt = iot_button_get_event(btn);
|
||||
switch (evt) {
|
||||
case BUTTON_PRESS_DOWN:
|
||||
ESP_LOGI(TAG, "BUTTON_PRESS_DOWN");
|
||||
break;
|
||||
case BUTTON_PRESS_UP:
|
||||
ESP_LOGI(TAG, "BUTTON_PRESS_UP");
|
||||
break;
|
||||
case BUTTON_PRESS_REPEAT:
|
||||
ESP_LOGI(TAG, "BUTTON_PRESS_REPEAT");
|
||||
break;
|
||||
case BUTTON_SINGLE_CLICK:
|
||||
ESP_LOGI(TAG, "BUTTON_SINGLE_CLICK");
|
||||
break;
|
||||
case BUTTON_DOUBLE_CLICK:
|
||||
ESP_LOGI(TAG, "BUTTON_DOUBLE_CLICK");
|
||||
break;
|
||||
case BUTTON_LONG_PRESS_START:
|
||||
ESP_LOGI(TAG, "BUTTON_LONG_PRESS_START");
|
||||
break;
|
||||
case BUTTON_LONG_PRESS_HOLD:
|
||||
ESP_LOGI(TAG, "BUTTON_LONG_PRESS_HOLD");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("gpio button test", "[button][iot]")
|
||||
{
|
||||
button_config_t cfg = {
|
||||
.type = BUTTON_TYPE_GPIO,
|
||||
.gpio_button_config = {
|
||||
.gpio_num = 0,
|
||||
.active_level = 0,
|
||||
},
|
||||
};
|
||||
g_btns[0] = iot_button_create(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(g_btns[0]);
|
||||
iot_button_register_cb(g_btns[0], BUTTON_PRESS_DOWN, button_press_down_cb);
|
||||
iot_button_register_cb(g_btns[0], BUTTON_PRESS_UP, button_press_up_cb);
|
||||
iot_button_register_cb(g_btns[0], BUTTON_PRESS_REPEAT, button_press_repeat_cb);
|
||||
iot_button_register_cb(g_btns[0], BUTTON_SINGLE_CLICK, button_single_click_cb);
|
||||
iot_button_register_cb(g_btns[0], BUTTON_DOUBLE_CLICK, button_double_click_cb);
|
||||
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_START, button_long_press_start_cb);
|
||||
iot_button_register_cb(g_btns[0], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb);
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
|
||||
iot_button_delete(g_btns[0]);
|
||||
}
|
||||
|
||||
TEST_CASE("adc button test", "[button][iot]")
|
||||
{
|
||||
/** ESP32-LyraT-Mini board */
|
||||
const uint16_t vol[6] = {380, 820, 1180, 1570, 1980, 2410};
|
||||
button_config_t cfg = {0};
|
||||
cfg.type = BUTTON_TYPE_ADC;
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
cfg.adc_button_config.adc_channel = 3,
|
||||
cfg.adc_button_config.button_index = i;
|
||||
if (i == 0) {
|
||||
cfg.adc_button_config.min = (0 + vol[i]) / 2;
|
||||
} else {
|
||||
cfg.adc_button_config.min = (vol[i - 1] + vol[i]) / 2;
|
||||
}
|
||||
|
||||
if (i == 5) {
|
||||
cfg.adc_button_config.max = (vol[i] + 3000) / 2;
|
||||
} else {
|
||||
cfg.adc_button_config.max = (vol[i] + vol[i + 1]) / 2;
|
||||
}
|
||||
|
||||
g_btns[i] = iot_button_create(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(g_btns[i]);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_PRESS_DOWN, button_press_down_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_PRESS_UP, button_press_up_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_PRESS_REPEAT, button_press_repeat_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_SINGLE_CLICK, button_single_click_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_DOUBLE_CLICK, button_double_click_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_START, button_long_press_start_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
iot_button_delete(g_btns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("adc gpio button test", "[button][iot]")
|
||||
{
|
||||
button_config_t cfg = {
|
||||
.type = BUTTON_TYPE_GPIO,
|
||||
.gpio_button_config = {
|
||||
.gpio_num = 0,
|
||||
.active_level = 0,
|
||||
},
|
||||
};
|
||||
g_btns[8] = iot_button_create(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(g_btns[8]);
|
||||
iot_button_register_cb(g_btns[8], BUTTON_PRESS_DOWN, button_press_down_cb);
|
||||
iot_button_register_cb(g_btns[8], BUTTON_PRESS_UP, button_press_up_cb);
|
||||
iot_button_register_cb(g_btns[8], BUTTON_PRESS_REPEAT, button_press_repeat_cb);
|
||||
iot_button_register_cb(g_btns[8], BUTTON_SINGLE_CLICK, button_single_click_cb);
|
||||
iot_button_register_cb(g_btns[8], BUTTON_DOUBLE_CLICK, button_double_click_cb);
|
||||
iot_button_register_cb(g_btns[8], BUTTON_LONG_PRESS_START, button_long_press_start_cb);
|
||||
iot_button_register_cb(g_btns[8], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb);
|
||||
|
||||
/** ESP32-LyraT-Mini board */
|
||||
const uint16_t vol[6] = {380, 820, 1180, 1570, 1980, 2410};
|
||||
// button_config_t cfg = {0};
|
||||
cfg.type = BUTTON_TYPE_ADC;
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
cfg.adc_button_config.adc_channel = 3,
|
||||
cfg.adc_button_config.button_index = i;
|
||||
if (i == 0) {
|
||||
cfg.adc_button_config.min = (0 + vol[i]) / 2;
|
||||
} else {
|
||||
cfg.adc_button_config.min = (vol[i - 1] + vol[i]) / 2;
|
||||
}
|
||||
|
||||
if (i == 5) {
|
||||
cfg.adc_button_config.max = (vol[i] + 3000) / 2;
|
||||
} else {
|
||||
cfg.adc_button_config.max = (vol[i] + vol[i + 1]) / 2;
|
||||
}
|
||||
|
||||
g_btns[i] = iot_button_create(&cfg);
|
||||
TEST_ASSERT_NOT_NULL(g_btns[i]);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_PRESS_DOWN, button_press_down_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_PRESS_UP, button_press_up_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_PRESS_REPEAT, button_press_repeat_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_SINGLE_CLICK, button_single_click_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_DOUBLE_CLICK, button_double_click_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_START, button_long_press_start_cb);
|
||||
iot_button_register_cb(g_btns[i], BUTTON_LONG_PRESS_HOLD, button_long_press_hold_cb);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
iot_button_delete(g_btns[i]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
||||
Reference in New Issue
Block a user