mirror of
https://github.com/MaJerle/lwbtn.git
synced 2026-09-26 15:33:40 +08:00
Merge branch 'develop'
This commit is contained in:
Vendored
+1
-4
@@ -1,15 +1,12 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
/* GDB must in be in the PATH environment */
|
||||
"name": "(Windows) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${command:cmake.launchTargetPath}",
|
||||
"miDebuggerPath": "c:\\msys64\\mingw64\\bin\\gdb.exe",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${fileDirname}",
|
||||
|
||||
Vendored
+3
-1
@@ -6,7 +6,9 @@
|
||||
"string.h": "c",
|
||||
"lwevt_opt.h": "c",
|
||||
"lwbtn.h": "c",
|
||||
"lwbtn_opt.h": "c"
|
||||
"lwbtn_opt.h": "c",
|
||||
"lwbtn_opts.h": "c",
|
||||
"compare": "c"
|
||||
},
|
||||
"esbonio.sphinx.confDir": ""
|
||||
}
|
||||
@@ -2,4 +2,15 @@
|
||||
|
||||
## Develop
|
||||
|
||||
## v0.0.2
|
||||
|
||||
- Add `LWBTN_CFG_GET_STATE_MODE` to control *get state* mode
|
||||
- Add option to check if button is currently active (after debounce period has elapsed)
|
||||
- Add option to set time/click parameters at run time for each button specifically
|
||||
- Rename `_RUNTIME` configuration with `_DYNAMIC`
|
||||
- Change `LWBTC_CFG_TIME_DEBOUNCE` to `LWBTC_CFG_TIME_DEBOUNCE_PRESS` and `LWBTC_CFG_TIME_DEBOUNCE_RUNTIME` to `LWBTC_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC` respectively
|
||||
- Add option release debounce with `LWBTC_CFG_TIME_DEBOUNCE_RELEASE` and `LWBTC_CFG_TIME_DEBOUNCE_RELEASE_DYNAMIC` options
|
||||
|
||||
## v0.0.1
|
||||
|
||||
- First commit
|
||||
@@ -12,6 +12,7 @@ else()
|
||||
# Add key executable block
|
||||
target_sources(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/dev/main.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/examples/example_win32.c
|
||||
)
|
||||
|
||||
# Add key include paths
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Tilen MAJERLE
|
||||
Copyright (c) 2023 Tilen MAJERLE
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+12
-2
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Tilen MAJERLE
|
||||
* Copyright (c) 2023 Tilen MAJERLE
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
@@ -29,7 +29,7 @@
|
||||
* This file is part of LwBTN - Lightweight button manager.
|
||||
*
|
||||
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||
* Version: v0.0.1
|
||||
* Version: v0.0.2
|
||||
*/
|
||||
#ifndef LWBTN_HDR_OPTS_H
|
||||
#define LWBTN_HDR_OPTS_H
|
||||
@@ -41,4 +41,14 @@
|
||||
* copy & replace here settings you want to change values
|
||||
*/
|
||||
|
||||
/* Press config */
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_PRESS 20 /* No debounce for press event */
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC \
|
||||
1 /* Debounce for press event is statically set with macro -> no dynamic config */
|
||||
|
||||
/* Release config */
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_RELEASE 20 /* No debounce for release event */
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_RELEASE_DYNAMIC \
|
||||
1 /* Debounce for release event is statically set with macro -> no dynamic config */
|
||||
|
||||
#endif /* LWBTN_HDR_OPTS_H */
|
||||
|
||||
+3
-98
@@ -3,105 +3,10 @@
|
||||
#include "lwbtn/lwbtn.h"
|
||||
#include "windows.h"
|
||||
|
||||
static LARGE_INTEGER freq, sys_start_time;
|
||||
static uint32_t get_tick(void);
|
||||
|
||||
/* User defined settings */
|
||||
const int keys[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
uint32_t last_time_keys[sizeof(keys) / sizeof(keys[0])] = {0};
|
||||
|
||||
/* List of buttons to process */
|
||||
static lwbtn_btn_t btns[] = {{.arg = (void*)&keys[0]}, {.arg = (void*)&keys[1]}, {.arg = (void*)&keys[2]},
|
||||
{.arg = (void*)&keys[3]}, {.arg = (void*)&keys[4]}, {.arg = (void*)&keys[5]},
|
||||
{.arg = (void*)&keys[6]}, {.arg = (void*)&keys[7]}, {.arg = (void*)&keys[8]},
|
||||
{.arg = (void*)&keys[9]}};
|
||||
|
||||
/**
|
||||
* \brief Get input state callback
|
||||
* \param lw: LwBTN instance
|
||||
* \param btn: Button instance
|
||||
* \return `1` if button active, `0` otherwise
|
||||
*/
|
||||
uint8_t
|
||||
prv_btn_get_state(struct lwbtn* lw, struct lwbtn_btn* btn) {
|
||||
(void)lw;
|
||||
return GetAsyncKeyState(*(int*)btn->arg) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Button event
|
||||
*
|
||||
* \param lw: LwBTN instance
|
||||
* \param btn: Button instance
|
||||
* \param evt: Button event
|
||||
*/
|
||||
void
|
||||
prv_btn_event(struct lwbtn* lw, struct lwbtn_btn* btn, lwbtn_evt_t evt) {
|
||||
const char* s;
|
||||
uint32_t color;
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
uint32_t* diff_time_ptr = &last_time_keys[(*(int*)btn->arg) - '0'];
|
||||
uint32_t diff_time = get_tick() - *diff_time_ptr;
|
||||
|
||||
/* This is for purpose of test and timing validation */
|
||||
if (diff_time > 2000) {
|
||||
diff_time = 0;
|
||||
}
|
||||
*diff_time_ptr = get_tick(); /* Set current date as last one */
|
||||
|
||||
/* Get event string */
|
||||
if (evt == LWBTN_EVT_KEEPALIVE) {
|
||||
s = "KEEPALIVE";
|
||||
color = FOREGROUND_RED;
|
||||
} else if (evt == LWBTN_EVT_ONPRESS) {
|
||||
s = " ONPRESS";
|
||||
color = FOREGROUND_GREEN;
|
||||
} else if (evt == LWBTN_EVT_ONRELEASE) {
|
||||
s = "ONRELEASE";
|
||||
color = FOREGROUND_BLUE;
|
||||
} else if (evt == LWBTN_EVT_ONCLICK) {
|
||||
s = " ONCLICK";
|
||||
color = FOREGROUND_RED | FOREGROUND_GREEN;
|
||||
} else {
|
||||
s = " UNKNOWN";
|
||||
color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
}
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
printf("[%7u][%6u] CH: %c, evt: %s, keep-alive cnt: %3u, click cnt: %3u\r\n", (unsigned)get_tick(),
|
||||
(unsigned)diff_time, *(int*)btn->arg, s, (unsigned)btn->keepalive.cnt, (unsigned)btn->click.cnt);
|
||||
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
(void)lw;
|
||||
}
|
||||
extern int example_win32(void);
|
||||
|
||||
int
|
||||
main(void) {
|
||||
printf("Application running\r\n");
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&sys_start_time);
|
||||
|
||||
/* Define buttons */
|
||||
lwbtn_init_ex(NULL, btns, sizeof(btns) / sizeof(btns[0]), prv_btn_get_state, prv_btn_event);
|
||||
|
||||
while (1) {
|
||||
/* Process forever */
|
||||
lwbtn_process_ex(NULL, get_tick());
|
||||
|
||||
/* Artificial sleep to offload win process */
|
||||
Sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get current tick in ms from start of program
|
||||
* \return uint32_t: Tick in ms
|
||||
*/
|
||||
static uint32_t
|
||||
get_tick(void) {
|
||||
LONGLONG ret;
|
||||
LARGE_INTEGER now;
|
||||
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&now);
|
||||
ret = now.QuadPart - sys_start_time.QuadPart;
|
||||
return (uint32_t)((ret * 1000) / freq.QuadPart);
|
||||
example_win32();
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ subprocess.call('doxygen doxyfile.doxy', shell=True)
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'LwBTN'
|
||||
copyright = '2022, Tilen MAJERLE'
|
||||
copyright = '2023, Tilen MAJERLE'
|
||||
author = 'Tilen MAJERLE'
|
||||
|
||||
# Try to get branch at which this is running
|
||||
|
||||
@@ -62,7 +62,7 @@ Next step is to add the library to the project, by means of source files to comp
|
||||
|
||||
* Copy ``lwbtn`` folder to your project, it contains library files
|
||||
* Add ``lwbtn/src/include`` folder to `include path` of your toolchain. This is where `C/C++` compiler can find the files during compilation process. Usually using ``-I`` flag
|
||||
* Add source files from ``lwbtn/src/`` folder to toolchain build. These files are built by `C/C++` compiler
|
||||
* Add source files from ``lwbtn/src/`` folder to toolchain build. These files are built by `C/C++` compiler. CMake configuration comes with the library, allows users to include library in the project as **subdirectory** and **library**.
|
||||
* Copy ``lwbtn/src/include/lwbtn/lwbtn_opts_template.h`` to project folder and rename it to ``lwbtn_opts.h``
|
||||
* Copy ``lwbtn/src/include/lwbtn/lwbtn_types_template.h`` to project folder and rename it to ``lwbtn_types.h``
|
||||
* Build the project
|
||||
|
||||
@@ -78,3 +78,4 @@ Table of contents
|
||||
LwRB - Ring buffer <https://github.com/MaJerle/lwrb>
|
||||
LwSHELL - Shell <https://github.com/MaJerle/lwshell>
|
||||
LwUTIL - Utility functions <https://github.com/MaJerle/lwutil>
|
||||
LwWDG - RTOS task watchdog <https://github.com/MaJerle/lwwdg>
|
||||
|
||||
@@ -19,6 +19,13 @@ User must define buttons array and pass it to the library. Next to that, ``2`` m
|
||||
|
||||
User shall later periodically call processing function with current system time as simple parameter and get ready to receive various events.
|
||||
|
||||
A simple example for win32 is below:
|
||||
|
||||
.. literalinclude:: ../../examples/example_win32.c
|
||||
:language: c
|
||||
:linenos:
|
||||
:caption: Win32 example code
|
||||
|
||||
Input events
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#include "lwbtn/lwbtn.h"
|
||||
#include "windows.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static LARGE_INTEGER freq, sys_start_time;
|
||||
static uint32_t get_tick(void);
|
||||
|
||||
/* User defined settings */
|
||||
const int keys[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
uint32_t last_time_keys[sizeof(keys) / sizeof(keys[0])] = {0};
|
||||
|
||||
/* List of buttons to process with assigned custom arguments for callback functions */
|
||||
static lwbtn_btn_t btns[] = {
|
||||
{.arg = (void*)&keys[0]}, {.arg = (void*)&keys[1]}, {.arg = (void*)&keys[2]}, {.arg = (void*)&keys[3]},
|
||||
{.arg = (void*)&keys[4]}, {.arg = (void*)&keys[5]}, {.arg = (void*)&keys[6]}, {.arg = (void*)&keys[7]},
|
||||
{.arg = (void*)&keys[8]}, {.arg = (void*)&keys[9]},
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Get input state callback
|
||||
* \param lw: LwBTN instance
|
||||
* \param btn: Button instance
|
||||
* \return `1` if button active, `0` otherwise
|
||||
*/
|
||||
uint8_t
|
||||
prv_btn_get_state(struct lwbtn* lw, struct lwbtn_btn* btn) {
|
||||
(void)lw;
|
||||
|
||||
/*
|
||||
* Function will return negative number if button is pressed,
|
||||
* or zero if button is releases
|
||||
*/
|
||||
return GetAsyncKeyState(*(int*)btn->arg) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Button event
|
||||
*
|
||||
* \param lw: LwBTN instance
|
||||
* \param btn: Button instance
|
||||
* \param evt: Button event
|
||||
*/
|
||||
void
|
||||
prv_btn_event(struct lwbtn* lw, struct lwbtn_btn* btn, lwbtn_evt_t evt) {
|
||||
const char* s;
|
||||
uint32_t color, keepalive_cnt = 0;
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
uint32_t* diff_time_ptr = &last_time_keys[(*(int*)btn->arg) - '0'];
|
||||
uint32_t diff_time = get_tick() - *diff_time_ptr;
|
||||
|
||||
/* This is for purpose of test and timing validation */
|
||||
if (diff_time > 2000) {
|
||||
diff_time = 0;
|
||||
}
|
||||
*diff_time_ptr = get_tick(); /* Set current date as last one */
|
||||
|
||||
/* Get event string */
|
||||
if (0) {
|
||||
#if LWBTN_CFG_USE_KEEPALIVE
|
||||
} else if (evt == LWBTN_EVT_KEEPALIVE) {
|
||||
s = "KEEPALIVE";
|
||||
color = FOREGROUND_RED;
|
||||
#endif /* LWBTN_CFG_USE_KEEPALIVE */
|
||||
} else if (evt == LWBTN_EVT_ONPRESS) {
|
||||
s = " ONPRESS";
|
||||
color = FOREGROUND_GREEN;
|
||||
} else if (evt == LWBTN_EVT_ONRELEASE) {
|
||||
s = "ONRELEASE";
|
||||
color = FOREGROUND_BLUE;
|
||||
} else if (evt == LWBTN_EVT_ONCLICK) {
|
||||
s = " ONCLICK";
|
||||
color = FOREGROUND_RED | FOREGROUND_GREEN;
|
||||
} else {
|
||||
s = " UNKNOWN";
|
||||
color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
}
|
||||
#if LWBTN_CFG_USE_KEEPALIVE
|
||||
keepalive_cnt = btn->keepalive.cnt;
|
||||
#endif
|
||||
SetConsoleTextAttribute(hConsole, color);
|
||||
printf("[%7u][%6u] CH: %c, evt: %s, keep-alive cnt: %3u, click cnt: %3u\r\n", (unsigned)get_tick(),
|
||||
(unsigned)diff_time, *(int*)btn->arg, s, (unsigned)keepalive_cnt, (unsigned)btn->click.cnt);
|
||||
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
(void)lw;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Example function
|
||||
*/
|
||||
int
|
||||
example_win32(void) {
|
||||
uint32_t time_last;
|
||||
printf("Application running\r\n");
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&sys_start_time);
|
||||
|
||||
/* Define buttons */
|
||||
lwbtn_init_ex(NULL, btns, sizeof(btns) / sizeof(btns[0]), prv_btn_get_state, prv_btn_event);
|
||||
|
||||
time_last = get_tick();
|
||||
while (1) {
|
||||
/* Process forever */
|
||||
lwbtn_process_ex(NULL, get_tick());
|
||||
|
||||
/* Manually read button state */
|
||||
#if LWBTN_CFG_GET_STATE_MODE == LWBTN_GET_STATE_MODE_MANUAL
|
||||
for (size_t i = 0; i < sizeof(btns) / sizeof(btns[0]); ++i) {
|
||||
lwbtn_set_btn_state(&btns[i], prv_btn_get_state(NULL, &btns[i]));
|
||||
}
|
||||
#endif /* LWBTN_CFG_GET_STATE_MODE == LWBTN_GET_STATE_MODE_MANUAL */
|
||||
|
||||
/* Check if specific button is active and do some action */
|
||||
if (lwbtn_is_btn_active(&btns[0])) {
|
||||
if ((get_tick() - time_last) > 200) {
|
||||
time_last = get_tick();
|
||||
printf("Button is active\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Artificial sleep to offload win process */
|
||||
Sleep(5);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get current tick in ms from start of program
|
||||
* \return uint32_t: Tick in ms
|
||||
*/
|
||||
static uint32_t
|
||||
get_tick(void) {
|
||||
LONGLONG ret;
|
||||
LARGE_INTEGER now;
|
||||
|
||||
QueryPerformanceFrequency(&freq);
|
||||
QueryPerformanceCounter(&now);
|
||||
ret = now.QuadPart - sys_start_time.QuadPart;
|
||||
return (uint32_t)((ret * 1000) / freq.QuadPart);
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "LwBTN",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "Lightweight button handler for embedded systems",
|
||||
"keywords": "lwbtn, button, input, manager, btn, lightweight, embedded",
|
||||
"repository": {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Tilen MAJERLE
|
||||
* Copyright (c) 2023 Tilen MAJERLE
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
@@ -29,7 +29,7 @@
|
||||
* This file is part of LwBTN - Lightweight button manager.
|
||||
*
|
||||
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||
* Version: v0.0.1
|
||||
* Version: v0.0.2
|
||||
*/
|
||||
#ifndef LWBTN_HDR_H
|
||||
#define LWBTN_HDR_H
|
||||
@@ -75,38 +75,47 @@ typedef enum {
|
||||
LWBTN_EVT_ONPRESS = 0x00, /*!< On press event - sent when valid press is detected (after debounce if enabled) */
|
||||
LWBTN_EVT_ONRELEASE, /*!< On release event - sent when valid release event is detected (from active to inactive) */
|
||||
LWBTN_EVT_ONCLICK, /*!< On Click event - sent when valid sequence of on-press and on-release events occurs */
|
||||
#if LWBTN_CFG_USE_KEEPALIVE || __DOXYGEN__
|
||||
LWBTN_EVT_KEEPALIVE, /*!< Keep alive event - sent periodically when button is active */
|
||||
#endif /* LWBTN_CFG_USE_KEEPALIVE || __DOXYGEN__ */
|
||||
} lwbtn_evt_t;
|
||||
|
||||
/**
|
||||
* \brief Button event function callback prototype
|
||||
* \param[in] lw: LwBTN instance
|
||||
* \param[in] lwobj: LwBTN instance
|
||||
* \param[in] btn: Button instance from array for which event occured
|
||||
* \param[in] evt: Event type
|
||||
*/
|
||||
typedef void (*lwbtn_evt_fn)(struct lwbtn* lw, struct lwbtn_btn* btn, lwbtn_evt_t evt);
|
||||
typedef void (*lwbtn_evt_fn)(struct lwbtn* lwobj, struct lwbtn_btn* btn, lwbtn_evt_t evt);
|
||||
|
||||
/**
|
||||
* \brief Get button/input state callback function
|
||||
* \param[in] lw: LwBTN instance
|
||||
* \param[in] lwobj: LwBTN instance
|
||||
* \param[in] btn: Button instance from array to read state
|
||||
* \return `1` when button is considered `active`, `0` otherwise
|
||||
*/
|
||||
typedef uint8_t (*lwbtn_get_state_fn)(struct lwbtn* lw, struct lwbtn_btn* btn);
|
||||
typedef uint8_t (*lwbtn_get_state_fn)(struct lwbtn* lwobj, struct lwbtn_btn* btn);
|
||||
|
||||
/**
|
||||
* \brief Button/input structure
|
||||
*/
|
||||
typedef struct lwbtn_btn {
|
||||
uint16_t flags; /*!< Private button flags management */
|
||||
uint8_t old_state; /*!< Old button state - `1` means active, `0` means inactive */
|
||||
uint32_t time_change; /*!< Time in ms when button state got changed last time */
|
||||
uint16_t flags; /*!< Private button flags management */
|
||||
#if LWBTN_CFG_GET_STATE_MODE != LWBTN_GET_STATE_MODE_CALLBACK || __DOXYGEN__
|
||||
uint8_t curr_state; /*!< Current button state to be processed. It is used
|
||||
to keep track when application manually sets the button state */
|
||||
#endif /* LWBTN_CFG_GET_STATE_MODE != LWBTN_GET_STATE_MODE_CALLBACK || __DOXYGEN__ */
|
||||
uint8_t old_state; /*!< Old button state - `1` means active, `0` means inactive */
|
||||
uint32_t time_change; /*!< Time in ms when button state got changed last time after valid debounce */
|
||||
uint32_t time_state_change; /*!< Time in ms when button state got changed last time */
|
||||
|
||||
#if LWBTN_CFG_USE_KEEPALIVE || __DOXYGEN__
|
||||
struct {
|
||||
uint32_t last_time; /*!< Time in ms of last send keep alive event */
|
||||
uint16_t cnt; /*!< Number of keep alive events sent after successful on-press detection.
|
||||
Value is reset after on-release */
|
||||
} keepalive; /*!< Keep alive structure */
|
||||
#endif /* LWBTN_CFG_USE_KEEPALIVE || __DOXYGEN__ */
|
||||
|
||||
struct {
|
||||
uint32_t last_time; /*!< Time in ms of last successfully detected (not sent!) click event */
|
||||
@@ -114,39 +123,76 @@ typedef struct lwbtn_btn {
|
||||
} click; /*!< Click event structure */
|
||||
|
||||
void* arg; /*!< User defined custom argument for callback function purpose */
|
||||
|
||||
#if LWBTN_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC || __DOXYGEN__
|
||||
uint16_t time_debounce; /*!< Debounce time in milliseconds */
|
||||
#endif /* LWBTN_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC || __DOXYGEN__ */
|
||||
#if LWBTN_CFG_TIME_DEBOUNCE_RELEASE_DYNAMIC || __DOXYGEN__
|
||||
uint16_t time_debounce_release; /*!< Debounce time in milliseconds for release event */
|
||||
#endif /* LWBTN_CFG_TIME_DEBOUNCE_RELEASE */
|
||||
#if LWBTN_CFG_TIME_CLICK_MIN_DYNAMIC || __DOXYGEN__
|
||||
uint16_t time_click_pressed_min; /*!< Minimum pressed time for valid click event */
|
||||
#endif /* LWBTN_CFG_TIME_CLICK_MIN_DYNAMIC || __DOXYGEN__ */
|
||||
#if LWBTN_CFG_TIME_CLICK_MAX_DYNAMIC || __DOXYGEN__
|
||||
uint16_t time_click_pressed_max; /*!< Maximum pressed time for valid click event*/
|
||||
#endif /* LWBTN_CFG_TIME_CLICK_MAX_DYNAMIC || __DOXYGEN__ */
|
||||
#if LWBTN_CFG_TIME_CLICK_MULTI_MAX_DYNAMIC || __DOXYGEN__
|
||||
uint16_t time_click_multi_max; /*!< Maximum time between 2 clicks to be considered consecutive click */
|
||||
#endif /* LWBTN_CFG_TIME_CLICK_MULTI_MAX_DYNAMIC || __DOXYGEN__ */
|
||||
#if LWBTN_CFG_TIME_KEEPALIVE_PERIOD_DYNAMIC || __DOXYGEN__
|
||||
uint16_t time_keepalive_period; /*!< Time in ms for periodic keep alive event */
|
||||
#endif /* LWBTN_CFG_TIME_KEEPALIVE_PERIOD_DYNAMIC || __DOXYGEN__ */
|
||||
#if LWBTN_CFG_CLICK_MAX_CONSECUTIVE_DYNAMIC || __DOXYGEN__
|
||||
uint16_t max_consecutive; /*!< Max number of consecutive clicks */
|
||||
#endif /* LWBTN_CFG_CLICK_MAX_CONSECUTIVE_DYNAMIC || __DOXYGEN__ */
|
||||
} lwbtn_btn_t;
|
||||
|
||||
/**
|
||||
* \brief LwBTN group structure
|
||||
*/
|
||||
typedef struct lwbtn {
|
||||
lwbtn_btn_t* btns; /*!< Pointer to buttons array */
|
||||
uint16_t btns_cnt; /*!< Number of buttons in array */
|
||||
lwbtn_evt_fn evt_fn; /*!< Pointer to event function */
|
||||
lwbtn_btn_t* btns; /*!< Pointer to buttons array */
|
||||
uint16_t btns_cnt; /*!< Number of buttons in array */
|
||||
lwbtn_evt_fn evt_fn; /*!< Pointer to event function */
|
||||
#if LWBTN_CFG_GET_STATE_MODE != LWBTN_GET_STATE_MODE_MANUAL || __DOXYGEN__
|
||||
lwbtn_get_state_fn get_state_fn; /*!< Pointer to get state function */
|
||||
#endif /* LWBTN_CFG_GET_STATE_MODE != LWBTN_GET_STATE_MODE_MANUAL || __DOXYGEN__ */
|
||||
} lwbtn_t;
|
||||
|
||||
uint8_t lwbtn_init_ex(lwbtn_t* lw, lwbtn_btn_t* btns, uint16_t btns_cnt, lwbtn_get_state_fn get_state_fn,
|
||||
uint8_t lwbtn_init_ex(lwbtn_t* lwobj, lwbtn_btn_t* btns, uint16_t btns_cnt, lwbtn_get_state_fn get_state_fn,
|
||||
lwbtn_evt_fn evt_fn);
|
||||
uint8_t lwbtn_process_ex(lwbtn_t* lw, uint32_t mstime);
|
||||
uint8_t lwbtn_process_ex(lwbtn_t* lwobj, uint32_t mstime);
|
||||
uint8_t lwbtn_process_btn_ex(lwbtn_t* lwobj, lwbtn_btn_t* btn, uint32_t mstime);
|
||||
uint8_t lwbtn_set_btn_state(lwbtn_btn_t* btn, uint8_t state);
|
||||
uint8_t lwbtn_is_btn_active(const lwbtn_btn_t* btn);
|
||||
|
||||
/**
|
||||
* \brief Initialize LwBTN library with buttons on default button group
|
||||
* \param[in] btns: Array of buttons to process
|
||||
* \param[in] btns_cnt: Number of buttons to process
|
||||
* \param[in] get_state_fn: Pointer to function providing button state on demand
|
||||
* \param[in] get_state_fn: Pointer to function providing button state on demand.
|
||||
* Can be set to `NULL` if \ref LWBTN_CFG_FORCE_MANUAL_STATE_SET is enabled
|
||||
* \param[in] evt_fn: Button event function callback
|
||||
* \sa lwbtn_init_ex
|
||||
*/
|
||||
#define lwbtn_init(btns, btns_cnt, get_state_fn, evt_fn) lwbtn_init_ex(NULL, btns, btns_cnt, get_state_fn, evt_fn)
|
||||
|
||||
/**
|
||||
* \brief Periodically read button states and take appropriate actions
|
||||
* \brief Periodically read button states and take appropriate actions.
|
||||
* It processes the default buttons instance group.
|
||||
* \param[in] mstime: Current system time in milliseconds
|
||||
* \sa lwbtn_process_ex
|
||||
*/
|
||||
#define lwbtn_process(mstime) lwbtn_process_ex(NULL, mstime)
|
||||
|
||||
/**
|
||||
* \brief Process specific button in a default LwBTN instance
|
||||
*
|
||||
* \param[in] btn: Button instance to process
|
||||
* \param[in] mstime: Current system time in milliseconds
|
||||
*/
|
||||
#define lwbtn_process_btn(btn, mstime) lwbtn_process_btn_ex(NULL, (btn), (mstime))
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Tilen MAJERLE
|
||||
* Copyright (c) 2023 Tilen MAJERLE
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
@@ -29,10 +29,10 @@
|
||||
* This file is part of LwBTN - Lightweight button manager.
|
||||
*
|
||||
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||
* Version: v0.0.1
|
||||
* Version: v0.0.2
|
||||
*/
|
||||
#ifndef LWBTN_HDR_OPT_H
|
||||
#define LWBTN_HDR_OPT_H
|
||||
#ifndef LWBTN_OPT_HDR_H
|
||||
#define LWBTN_OPT_HDR_H
|
||||
|
||||
/* Uncomment to ignore user options (or set macro in compiler flags) */
|
||||
/* #define LWBTN_IGNORE_USER_OPTS */
|
||||
@@ -53,12 +53,67 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Minimum debounce time in units of milliseconds
|
||||
* \brief Enables `1` or disables `0` periodic keep alive events.
|
||||
*
|
||||
* This is the time input shall have stable level to detect valid *onpress* event
|
||||
* Default keep alive period is set with \ref LWBTN_CFG_TIME_KEEPALIVE_PERIOD macro
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_DEBOUNCE
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE 20
|
||||
#ifndef LWBTN_CFG_USE_KEEPALIVE
|
||||
#define LWBTN_CFG_USE_KEEPALIVE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Minimum debounce time for press event in units of milliseconds
|
||||
*
|
||||
* This is the time when the input shall have stable active level to detect valid *onpress* event.
|
||||
*
|
||||
* This is used to detect initial debounce when button/input is being pressed by the user.
|
||||
*
|
||||
* When value is set to `> 0`, input must be in active state for at least
|
||||
* minimum milliseconds time, before valid *onpress* event is detected
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_DEBOUNCE_PRESS
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_PRESS 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` dynamic settable time debounce
|
||||
*
|
||||
* When enabled, additional field is added to button structure to allow
|
||||
* each button setting its very own debounce time for press event.
|
||||
*
|
||||
* If not used, \ref LWBTN_CFG_TIME_DEBOUNCE_PRESS is used as default
|
||||
* debouncing configuration
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_PRESS_DYNAMIC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Minimum debounce time for release event in units of milliseconds
|
||||
*
|
||||
* This is the time when the input shall have stable released level to detect valid *onrelease* event.
|
||||
*
|
||||
* This setting can be useful if application wants to protect against
|
||||
* unwanted glitches on the line when input is considered "active".
|
||||
*
|
||||
* When value is set to `> 0`, input must be in inactive low for at least
|
||||
* minimum milliseconds time, before valid *onrelease* event is detected
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_DEBOUNCE_RELEASE
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_RELEASE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` dynamic settable time debounce for release event
|
||||
*
|
||||
* When enabled, additional field is added to button structure to allow
|
||||
* each button setting its very own debounce time for release event.
|
||||
*
|
||||
* If not used, \ref LWBTN_CFG_TIME_DEBOUNCE_RELEASE is used as default
|
||||
* debouncing configuration
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_DEBOUNCE_RELEASE_DYNAMIC
|
||||
#define LWBTN_CFG_TIME_DEBOUNCE_RELEASE_DYNAMIC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -71,6 +126,15 @@ extern "C" {
|
||||
#define LWBTN_CFG_TIME_CLICK_MIN 20
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` dynamic settable min time for click
|
||||
*
|
||||
* When enabled, additional field is added to button structure
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_CLICK_MIN_DYNAMIC
|
||||
#define LWBTN_CFG_TIME_CLICK_MIN_DYNAMIC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Maximum active input time for valid click event, in milliseconds
|
||||
*
|
||||
@@ -81,6 +145,15 @@ extern "C" {
|
||||
#define LWBTN_CFG_TIME_CLICK_MAX 300
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` dynamic settable max time for click
|
||||
*
|
||||
* When enabled, additional field is added to button structure
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_CLICK_MAX_DYNAMIC
|
||||
#define LWBTN_CFG_TIME_CLICK_MAX_DYNAMIC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Maximum allowed time between last on-release and next valid on-press,
|
||||
* to still allow multi-click events, in milliseconds
|
||||
@@ -92,12 +165,30 @@ extern "C" {
|
||||
#define LWBTN_CFG_TIME_CLICK_MULTI_MAX 400
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` dynamic settable max time for multi click
|
||||
*
|
||||
* When enabled, additional field is added to button structure
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_CLICK_MULTI_MAX_DYNAMIC
|
||||
#define LWBTN_CFG_TIME_CLICK_MULTI_MAX_DYNAMIC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Maximum number of allowed consecutive click events,
|
||||
* before structure gets reset to default value
|
||||
*/
|
||||
#ifndef LWBTN_CFG_CLICK_MAX_CONSECUTIVE
|
||||
#define LWBTN_CFG_CLICK_MAX_CONSECUTIVE 1
|
||||
#define LWBTN_CFG_CLICK_MAX_CONSECUTIVE 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` dynamic settable max consecutive clicks
|
||||
*
|
||||
* When enabled, additional field is added to button structure
|
||||
*/
|
||||
#ifndef LWBTN_CFG_CLICK_MAX_CONSECUTIVE_DYNAMIC
|
||||
#define LWBTN_CFG_CLICK_MAX_CONSECUTIVE_DYNAMIC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -108,6 +199,15 @@ extern "C" {
|
||||
#define LWBTN_CFG_TIME_KEEPALIVE_PERIOD 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` dynamic settable keep alive period
|
||||
*
|
||||
* When enabled, additional field is added to button structure
|
||||
*/
|
||||
#ifndef LWBTN_CFG_TIME_KEEPALIVE_PERIOD_DYNAMIC
|
||||
#define LWBTN_CFG_TIME_KEEPALIVE_PERIOD_DYNAMIC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Enables `1` or disables `0` immediate onclick event
|
||||
* after on-release event, if number of consecutive
|
||||
@@ -122,6 +222,28 @@ extern "C" {
|
||||
#define LWBTN_CFG_CLICK_MAX_CONSECUTIVE_SEND_IMMEDIATELY 1
|
||||
#endif
|
||||
|
||||
#define LWBTN_GET_STATE_MODE_CALLBACK 0 /*!< Callback-only state mode */
|
||||
#define LWBTN_GET_STATE_MODE_MANUAL 1 /*!< Manual-only state mode */
|
||||
#define LWBTN_GET_STATE_MODE_CALLBACK_OR_MANUAL 2 /*!< Callback or manual state mode */
|
||||
|
||||
/**
|
||||
* \brief Sets the mode how new button state is acquired.
|
||||
*
|
||||
* Different modes are availale, set with the level number:
|
||||
*
|
||||
* - `LWBTN_GET_STATE_MODE_CALLBACK`: State of the button is checked through *get state* callback function (default mode, legacy)
|
||||
* - `LWBTN_GET_STATE_MODE_MANUAL`: Only manual state set is enabled. Application must set the button state with API functions.
|
||||
* Callback API is not used.
|
||||
* - `LWBTN_GET_STATE_MODE_CALLBACK_OR_MANUAL`: State of the button is checked through *get state* callback function (by default).
|
||||
* It enables API to manually set the state with approapriate function call.
|
||||
* Button state is checked with the callback at least until manual state API function is called.
|
||||
*
|
||||
* This allows multiple build configurations for various button types
|
||||
*/
|
||||
#ifndef LWBTN_CFG_GET_STATE_MODE
|
||||
#define LWBTN_CFG_GET_STATE_MODE LWBTN_GET_STATE_MODE_CALLBACK
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
@@ -130,4 +252,4 @@ extern "C" {
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* LWBTN_HDR_OPT_H */
|
||||
#endif /* LWBTN_OPT_HDR_H */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Tilen MAJERLE
|
||||
* Copyright (c) 2023 Tilen MAJERLE
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
@@ -29,10 +29,10 @@
|
||||
* This file is part of LwBTN - Lightweight button manager.
|
||||
*
|
||||
* Author: Tilen MAJERLE <tilen@majerle.eu>
|
||||
* Version: v0.0.1
|
||||
* Version: v0.0.2
|
||||
*/
|
||||
#ifndef LWBTN_HDR_OPTS_H
|
||||
#define LWBTN_HDR_OPTS_H
|
||||
#ifndef LWBTN_OPTS_HDR_H
|
||||
#define LWBTN_OPTS_HDR_H
|
||||
|
||||
/* Rename this file to "lwbtn_opts.h" for your application */
|
||||
|
||||
@@ -41,4 +41,4 @@
|
||||
* copy & replace here settings you want to change values
|
||||
*/
|
||||
|
||||
#endif /* LWBTN_HDR_OPTS_H */
|
||||
#endif /* LWBTN_OPTS_HDR_H */
|
||||
|
||||
+315
-158
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user