File syn_button.h¶
File List > input > syn_button.h
Go to the documentation of this file
#ifndef SYN_BUTTON_H
#define SYN_BUTTON_H
#include "../common/syn_defs.h"
#include "../drivers/syn_gpio.h"
#include "../port/syn_port_system.h"
#include "../util/syn_fsm.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ── Button polarity ────────────────────────────────────────────────────── */
typedef enum {
SYN_BUTTON_ACTIVE_HIGH = 0,
SYN_BUTTON_ACTIVE_LOW = 1,
} SYN_ButtonPolarity;
/* ── Button state ───────────────────────────────────────────────────────── */
typedef enum {
SYN_BUTTON_STATE_IDLE = 0,
SYN_BUTTON_STATE_DEBOUNCING = 1,
SYN_BUTTON_STATE_PRESSED = 2,
SYN_BUTTON_STATE_HELD = 3,
} SYN_ButtonState;
#define SYN_BUTTON_EVT_PRESS ((uint8_t)(1u << 0))
#define SYN_BUTTON_EVT_RELEASE ((uint8_t)(1u << 1))
#define SYN_BUTTON_EVT_LONG_PRESS ((uint8_t)(1u << 2))
#define SYN_BUTTON_EVT_REPEAT ((uint8_t)(1u << 3))
#define SYN_BUTTON_EVT_SINGLE_CLICK ((uint8_t)(1u << 4))
#define SYN_BUTTON_EVT_DOUBLE_CLICK ((uint8_t)(1u << 5))
#define SYN_BUTTON_EVT_TRIPLE_CLICK ((uint8_t)(1u << 6))
#define SYN_BUTTON_EVT_MULTI_CLICK ((uint8_t)(1u << 7))
/* ── Callback type ──────────────────────────────────────────────────────── */
struct SYN_Button;
typedef void (*SYN_ButtonCallback)(struct SYN_Button *btn, void *user_data);
/* ── Button descriptor ──────────────────────────────────────────────────── */
typedef struct SYN_Button {
/* Configuration */
SYN_GPIO_Pin pin;
uint8_t polarity;
uint16_t debounce_ms;
uint16_t long_press_ms;
uint16_t repeat_ms;
uint16_t double_click_ms;
/* State */
SYN_FSM fsm;
uint8_t events;
bool raw_pressed;
bool pressed;
bool in_combo;
uint8_t click_count;
uint32_t state_tick;
uint32_t repeat_tick;
uint32_t click_tick;
/* Callbacks */
SYN_ButtonCallback on_press;
void *on_press_ctx;
SYN_ButtonCallback on_release;
void *on_release_ctx;
SYN_ButtonCallback on_long_press;
void *on_long_press_ctx;
SYN_ButtonCallback on_repeat;
void *on_repeat_ctx;
SYN_ButtonCallback on_single_click;
void *on_single_click_ctx;
SYN_ButtonCallback on_double_click;
void *on_double_click_ctx;
SYN_ButtonCallback on_triple_click;
void *on_triple_click_ctx;
SYN_ButtonCallback on_multi_click;
void *on_multi_click_ctx;
} SYN_Button;
/* ── Combo button descriptor ────────────────────────────────────────────── */
typedef struct SYN_ButtonCombo {
const SYN_Button **buttons;
size_t count;
SYN_ButtonCallback on_combo;
void *on_combo_ctx;
bool active;
uint8_t events;
} SYN_ButtonCombo;
/* ── Initialization ─────────────────────────────────────────────────────── */
void syn_button_init(SYN_Button *btn, SYN_GPIO_Pin pin, SYN_ButtonPolarity polarity,
uint16_t debounce_ms);
/* ── Configuration ──────────────────────────────────────────────────────── */
void syn_button_set_click_window(SYN_Button *btn, uint16_t window_ms);
/* ── Callback registration ──────────────────────────────────────────────── */
void syn_button_on_press(SYN_Button *btn, SYN_ButtonCallback cb, void *ctx);
void syn_button_on_release(SYN_Button *btn, SYN_ButtonCallback cb, void *ctx);
void syn_button_on_long_press(SYN_Button *btn, SYN_ButtonCallback cb, uint16_t hold_ms, void *ctx);
void syn_button_on_repeat(SYN_Button *btn, SYN_ButtonCallback cb, uint16_t interval_ms, void *ctx);
void syn_button_on_single_click(SYN_Button *btn, SYN_ButtonCallback cb, void *ctx);
void syn_button_on_double_click(SYN_Button *btn, SYN_ButtonCallback cb, void *ctx);
void syn_button_on_triple_click(SYN_Button *btn, SYN_ButtonCallback cb, void *ctx);
void syn_button_on_multi_click(SYN_Button *btn, SYN_ButtonCallback cb, void *ctx);
/* ── Combo button functions ─────────────────────────────────────────────── */
void syn_button_combo_init(SYN_ButtonCombo *combo, const SYN_Button **buttons, size_t count,
SYN_ButtonCallback cb, void *ctx);
void syn_button_combo_update(SYN_ButtonCombo *combo);
/* ── Update / service ───────────────────────────────────────────────────── */
void syn_button_update(SYN_Button *btn);
void syn_button_service(SYN_Button *buttons, size_t count);
/* ── Query ──────────────────────────────────────────────────────────────── */
static inline bool syn_button_is_pressed(const SYN_Button *btn)
{
return btn->pressed;
}
static inline uint32_t syn_button_held_ms(const SYN_Button *btn)
{
return syn_port_get_tick_ms() - btn->state_tick;
}
static inline uint8_t syn_button_clicks(const SYN_Button *btn)
{
return btn->click_count;
}
static inline bool syn_button_combo_is_active(const SYN_ButtonCombo *combo)
{
return combo != NULL && combo->active;
}
static inline uint8_t syn_button_poll_events(SYN_Button *btn)
{
uint8_t e = btn->events;
btn->events = 0;
return e;
}
/* ── Protothread integration ────────────────────────────────────────────── */
#define PT_WAIT_BUTTON_PRESS(pt, btn) \
PT_WAIT_UNTIL(pt, (btn)->events &SYN_BUTTON_EVT_PRESS); \
(btn)->events &= (uint8_t)~SYN_BUTTON_EVT_PRESS
#define PT_WAIT_BUTTON_RELEASE(pt, btn) \
PT_WAIT_UNTIL(pt, (btn)->events &SYN_BUTTON_EVT_RELEASE); \
(btn)->events &= (uint8_t)~SYN_BUTTON_EVT_RELEASE
#ifdef __cplusplus
}
#endif
#endif /* SYN_BUTTON_H */