| name | tuyaopen/peripheral-button |
| description | TDL button input handling for TuyaOpen: create button, register event callbacks for single click, double click, long press, and multi-click. 按键、单击、双击、长按、多击、按键事件。 |
| when_to_use | Use when the user wants to detect button presses: single click, double click, long press start/hold, or multi-click events. |
| id | peripheral-button |
| surfaces | ["embedded"] |
| tags | ["button","gpio","input","event"] |
TuyaOpen TDL Button
Driver Registration (TDD)
Decide by adaptation, not by whether the SDK has the driver — tdd_gpio_button
ships in the SDK either way:
- Board-adapted button (listed in
board-context.md) → board_register_hardware()
registers it automatically; write no TDD code.
- Externally-attached button (the user wired their own button — NOT in
board-context.md, e.g. "extra button on GPIO7") → register it yourself in
usr_board (see usr-board/SKILL.md). You still reuse the existing
tdd_gpio_button_register — board_register_hardware() does not wire a
button it never adapted. Put the __usr_register_button() below into
usr_board.c and call it from usr_register_hardware():
#include "tdd_button_gpio.h"
static OPERATE_RET __usr_register_button(void)
{
BUTTON_GPIO_CFG_T btn_cfg = {
.pin = TUYA_GPIO_NUM_17,
.level = TUYA_GPIO_LEVEL_LOW,
.mode = BUTTON_IRQ_MODE,
.pin_type.irq_edge = TUYA_GPIO_IRQ_FALL,
};
return tdd_gpio_button_register(BUTTON_NAME, &btn_cfg);
}
Pin and active level: for a board-adapted button, read its pins from
.tuyaopen/ide/board.json (by ID:); for an externally-attached button,
use the GPIO/level the user gave (must be a gpio from board.json.expansionPins).
New button IC with no SDK driver (still in usr_board)
Reusing tdd_gpio_button_register covers ordinary GPIO buttons. Only when the
button needs a TDD driver the SDK does not have (e.g. capacitive touch key,
I2C keypad) do you also write tdd_button_<ic>.h/.c inside usr_board/ and
implement tdl_button_register() with the callbacks. This is an addition to the
usr_board flow, not an alternative to it.
Headers
#include "tdl_button_manage.h"
Usage Template
#include "tal_api.h"
#include "tkl_output.h"
#include "tdl_button_manage.h"
static void button_event_cb(char *name, TDL_BUTTON_TOUCH_EVENT_E event, void *argc)
{
switch (event) {
case TDL_BUTTON_PRESS_DOWN: PR_NOTICE("%s: press down", name); break;
case TDL_BUTTON_PRESS_UP: PR_NOTICE("%s: press up", name); break;
case TDL_BUTTON_PRESS_SINGLE_CLICK: PR_NOTICE("%s: single click", name); break;
case TDL_BUTTON_PRESS_DOUBLE_CLICK: PR_NOTICE("%s: double click", name); break;
case TDL_BUTTON_LONG_PRESS_START: PR_NOTICE("%s: long press", name); break;
default: break;
}
}
void user_main(void)
{
tal_log_init(TAL_LOG_LEVEL_DEBUG, 4096, (TAL_LOG_OUTPUT_CB)tkl_log_output);
TDL_BUTTON_CFG_T button_cfg = {
.long_start_valid_time = 3000,
.long_keep_timer = 1000,
.button_debounce_time = 50,
.button_repeat_valid_count = 2,
.button_repeat_valid_time = 500,
};
TDL_BUTTON_HANDLE button_hdl = NULL;
TUYA_CALL_ERR_GOTO(tdl_button_create(BUTTON_NAME, &button_cfg, &button_hdl), EXIT);
tdl_button_event_register(button_hdl, TDL_BUTTON_PRESS_SINGLE_CLICK, button_event_cb);
tdl_button_event_register(button_hdl, TDL_BUTTON_LONG_PRESS_START, button_event_cb);
EXIT:
return;
}
API Reference
| Function | Description |
|---|
tdl_button_create(name, &cfg, &hdl) | Create button with timing config |
tdl_button_event_register(hdl, event, cb) | Register callback for one event type |
tdl_button_delete(hdl) | Delete button and release hardware |
tdl_button_read_status(hdl, &status) | Read current state (0=released, 1=pressed) |
tdl_button_set_scan_time(ms) | Set scan interval (default 10 ms) |
Event Types
| Event | Description |
|---|
TDL_BUTTON_PRESS_DOWN | Pressed |
TDL_BUTTON_PRESS_UP | Released |
TDL_BUTTON_PRESS_SINGLE_CLICK | Single click |
TDL_BUTTON_PRESS_DOUBLE_CLICK | Double click |
TDL_BUTTON_PRESS_REPEAT | Multi-click (≥ button_repeat_valid_count times) |
TDL_BUTTON_LONG_PRESS_START | Long press start (held ≥ long_start_valid_time ms) |
TDL_BUTTON_LONG_PRESS_HOLD | Long press hold (fires every long_keep_timer ms) |
Multiple Buttons
#if defined(BUTTON_NAME_2)
TDL_BUTTON_HANDLE button_hdl_2 = NULL;
tdl_button_create(BUTTON_NAME_2, &button_cfg, &button_hdl_2);
tdl_button_event_register(button_hdl_2, TDL_BUTTON_PRESS_SINGLE_CLICK, button_event_cb);
#endif
Enable Macro and NAME Macro
CONFIG_ENABLE_BUTTON=y # enables button and defines BUTTON_NAME
CONFIG_BUTTON_NAME="button1" # device name (default "button1")
BUTTON_NAME is passed to tdl_button_create().
Additional buttons use BUTTON_NAME_2, BUTTON_NAME_3 (requires enabling ENABLE_BUTTON_2, etc.).
Reference Example
examples/peripherals/button/