SLS AVR Lib 0.1a
 
Loading...
Searching...
No Matches
button.h
Go to the documentation of this file.
1// ---------------------------------------------------------------------------+
2// This file is part of SLS AVR Library
3// https://github.com/SimonLitt/sls-avr-lib
4// ---------------------------------------------------------------------------+
5// Copyright (C) 2025 Simon Litt <simon@1itt.net> https://coding.1itt.net,
6// https://github.com/SimonLitt
7//
8// This program is free software: you can redistribute it and/or modify it
9// under the terms of the GNU General Public License as published by the Free
10// Software Foundation, version 3.
11//
12// This program is distributed in the hope that it will be useful, but WITHOUT
13// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15// more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program. If not, see <https://www.gnu.org/licenses/>.
19// ---------------------------------------------------------------------------+
54#ifndef SLS_AVR_SINGLE_BUTTON_H_
55#define SLS_AVR_SINGLE_BUTTON_H_
56
57#include <string.h>
58#include <stdint.h>
59#include <util/atomic.h>
60#include <sls-avr/avr.h>
61
62#define BTN_MAX_SCAN_COUNT 254U
63
64#ifndef BTN_LONG_COUNT
65# define BTN_LONG_COUNT 40U
66# if (BTN_LONG_COUNT > BTN_MAX_SCAN_COUNT)
67# error "Long Pressed state counter should be less or equal to 254!"
68# endif
69# if (BTN_LONG_COUNT <= BTN_DOWN_COUNT)
70# error "Long Pressed state counter should be more then #BTN_DOWN_COUNT!"
71# endif
72#endif // BTN_LONG_COUNT
73
74#ifndef BTN_ALLOW_LONG
75# define BTN_ALLOW_LONG 0
76#endif // BTN_ALLOW_LONG
77
78#ifndef BTN_RESET_UNUSED_COUNT
79# define BTN_RESET_UNUSED_COUNT 0
80#endif // BTN_RESET_UNUSED_COUNT
81#if (BTN_RESET_UNUSED_COUNT < 0) || (BTN_RESET_UNUSED_COUNT > BTN_MAX_SCAN_COUNT)
82# error "Reset counter should be in range 0-254!"
83#endif
84
85#ifndef BTN_DOWN_COUNT
86#define BTN_DOWN_COUNT 3U
87#endif // BTN_DOWN_COUNT
88
89#if (BTN_DOWN_COUNT < 1) || (BTN_DOWN_COUNT > BTN_MAX_SCAN_COUNT)
90# error "Pressed state counter should be in range 2-254!"
91#endif
92
93#ifndef BTN_UP_COUNT
94# define BTN_UP_COUNT 2U
95#endif // BTN_UP_COUNT
96#if (BTN_UP_COUNT < 0) || (BTN_UP_COUNT > BTN_MAX_SCAN_COUNT)
97# error "Released state counter should be in range 1-254!"
98#endif
99
101#if !BTN_UP_COUNT
102# if BTN_ALLOW_LONG
103# error "Long presses are incompatible with fast processing!"
104# endif
105# define __BTN_ALLOW_FAST_SCAN
106#endif
108
109#ifndef BTN_FAST_SOME_CODE
110# define BTN_FAST_SOME_CODE 0
111#endif // BTN_FAST_SOME_CODE
112
114#if BTN_FAST_SOME_CODE && (defined(__BTN_ALLOW_FAST_SCAN) || !BTN_ALLOW_LONG)
115# define __BTN_LONG_DEFINITIONS
116#endif
118
120// ---------------------------------------------------------------------------+
121// state flags
122// ---------------------------------------------------------------------------+
123#define __BTN_STAGE_MAY_SHORT_BIT 0
124#if BTN_ALLOW_LONG
125# define __BTN_STAGE_MAY_LONG_BIT 1
126#endif // BTN_ALLOW_LONG
127#define __BTN_STAGE_PROCESSED_BIT 2
128//#define __BTN_STAGE_UNUSED_BIT 3
129#define __BTN_STATE_SHORT_CLICK_BIT 4
130#if BTN_ALLOW_LONG
131# define __BTN_STATE_LONG_CLICK_BIT 5
132#endif // BTN_ALLOW_LONG
133//#define __BTN_STAGE_UNUSED_BIT 6
134//#define __BTN_STAGE_UNUSED_BIT 7
135
136// Stages of click processing
137#define _BTN_STAGE_MAY_SHORT (_BV(__BTN_STAGE_MAY_SHORT_BIT))
138#define _BTN_STAGE_MAY_LONG (_BV(__BTN_STAGE_MAY_LONG_BIT))
139#define _BTN_STAGE_PROCESSED (_BV(__BTN_STAGE_PROCESSED_BIT))
140
141// States of a button
142#define _BTN_STATE_SHORT_CLICK (_BV(__BTN_STATE_SHORT_CLICK_BIT))
143#if BTN_ALLOW_LONG
144# define _BTN_STATE_LONG_CLICK (_BV(__BTN_STATE_LONG_CLICK_BIT))
145#endif // BTN_ALLOW_LONG
146
147#if BTN_ALLOW_LONG
148# define __BTN_IS_CLICKED (_BTN_STATE_SHORT_CLICK | _BTN_STATE_LONG_CLICK)
149# define __BTN_IS_HOLDED (_BTN_STAGE_MAY_SHORT | _BTN_STAGE_MAY_LONG)
150#else
151# define __BTN_IS_CLICKED _BTN_STATE_SHORT_CLICK
152# define __BTN_IS_HOLDED _BTN_STAGE_MAY_SHORT
153#endif // BTN_ALLOW_LONG
154
156
158typedef struct {
159 uint8_t _counter;
160 #ifndef __BTN_ALLOW_FAST_SCAN
161 uint8_t _up_counter;
162 #endif // __BTN_ALLOW_FAST_SCAN
165
166typedef volatile btn_info_struct btn_info_t;
167
168#define BTN_INFO_STATE_DEFAULT 0
169
170#ifndef __BTN_ALLOW_FAST_SCAN
171# define BTN_INFO_STRUCT_DEFAULT {._counter = 0, ._up_counter = 0, .state = BTN_INFO_STATE_DEFAULT}
172#else
173# define BTN_INFO_STRUCT_DEFAULT {._counter = 0, .state = BTN_INFO_STATE_DEFAULT}
174#endif // __BTN_ALLOW_FAST_SCAN
179#define btn_is_holded(_state) ((_state) & (__BTN_IS_HOLDED))
180
185#define btn_is_ready(_state) ((_state) & (__BTN_IS_CLICKED))
190#define btn_is_clicked(_state) (flag_is_set((_state), __BTN_STATE_SHORT_CLICK_BIT))
191
192#if defined(__DOXYGEN__)
197# define btn_is_long_clicked(_state)
198#endif // __DOXYGEN__
199
200#if BTN_ALLOW_LONG
201# define btn_is_long_clicked(_state) (flag_is_set((_state), __BTN_STATE_LONG_CLICK_BIT))
202#elifdef __BTN_LONG_DEFINITIONS
203# define btn_is_long_clicked(_state) false
204#endif // BTN_ALLOW_LONG
210#define btn_set_processed(_state) ((_state) = ((_state) & ~(__BTN_IS_CLICKED)) | _BTN_STAGE_PROCESSED)
211
212#ifndef BTN_ATOMIC_FUNCTIONS
213# define BTN_ATOMIC_FUNCTIONS 0
214#endif // BTN_ATOMIC_FUNCTIONS
215
217static inline void _btn_reset(btn_info_t *const btn_info) {
218 static const btn_info_struct _def_btn_info_struct = BTN_INFO_STRUCT_DEFAULT;
219 (*btn_info) = _def_btn_info_struct;
220}
222
226static inline void btn_reset(btn_info_t *const btn_info) {
227 #if defined(__BTN_ALLOW_FAST_SCAN) && BTN_FAST_SOME_CODE
228 btn_set_processed(btn_info->state);
229 #else
230 _btn_reset(btn_info);
231 #endif // __BTN_ALLOW_FAST_SCAN
232}
233
240void btn_proc(btn_info_t *const btn_info, const bool is_now_hold);
241
242#if defined(__DOXYGEN__)
243
247static inline void btn_reset_atomic(btn_info_t *const btn_info);
248
252static inline void btn_reset_atomic_fegi(btn_info_t *const btn_info);
253
258static inline void btn_proc_atomic(btn_info_t *const btn_info, const bool is_now_hold);
259
264static inline void btn_proc_atomic_fegi(btn_info_t *const btn_info, const bool is_now_hold);
265
270static inline btn_info_struct btn_get_info(btn_info_t *const btn_info);
271
274static inline btn_info_struct btn_get_info_fegi(btn_info_t *const btn_info);
275#endif // __DOXYGEN__
276
277#if BTN_ATOMIC_FUNCTIONS
278static inline void btn_reset_atomic(btn_info_t *const btn_info) {
279 #if defined(__BTN_ALLOW_FAST_SCAN) && BTN_FAST_SOME_CODE
280 btn_set_processed(btn_info->state); //8-bit - no atomic
281 #else
282 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
283 _btn_reset(btn_info);
284 }
285 #endif // __BTN_ALLOW_FAST_SCAN
286}
287
288static inline void btn_reset_atomic_fegi(btn_info_t *const btn_info) {
289 #if defined(__BTN_ALLOW_FAST_SCAN) && BTN_FAST_SOME_CODE
290 btn_set_processed(btn_info->state); //8-bit - no atomic
291 #else
292 ATOMIC_BLOCK(ATOMIC_FORCEON) {
293 _btn_reset(btn_info);
294 }
295 #endif // __BTN_ALLOW_FAST_SCAN
296}
297
298static inline void btn_proc_atomic(btn_info_t *const btn_info, const bool is_now_hold) {
299 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
300 btn_proc(btn_info, is_now_hold);
301 }
302}
303
304static inline void btn_proc_atomic_fegi(btn_info_t *const btn_info, const bool is_now_hold) {
305 ATOMIC_BLOCK(ATOMIC_FORCEON) {
306 btn_proc(btn_info, is_now_hold);
307 }
308}
309
310static inline btn_info_struct btn_get_info(btn_info_t *const btn_info) {
311 btn_info_struct info_struct;
312 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
313 info_struct = *btn_info;
314 }
315 return info_struct;
316}
317
318static inline btn_info_struct btn_get_info_fegi(btn_info_t *const btn_info) {
319 btn_info_struct info_struct;
320 ATOMIC_BLOCK(ATOMIC_FORCEON) {
321 info_struct = *btn_info;
322 }
323 return info_struct;
324}
325#endif // BTN_ATOMIC_FUNCTIONS
326
327#endif /* SLS_AVR_SINGLE_BUTTON_H_ */
AVR lib.
#define btn_set_processed(_state)
Is the button taken into account.
Definition button.h:210
static void btn_reset(btn_info_t *const btn_info)
Resets the button state to default.
Definition button.h:226
volatile btn_info_struct btn_info_t
Information about a button type. See btn_info_struct.
Definition button.h:166
static btn_info_struct btn_get_info_fegi(btn_info_t *const btn_info)
Such as the btn_get_info, but with force enabling ot the global interrupts.
static void btn_reset_atomic(btn_info_t *const btn_info)
Such as the btn_reset, but executed atomically.
static void btn_proc_atomic_fegi(btn_info_t *const btn_info, const bool is_now_hold)
Such as the btn_proc, but executed atomically with force enabling ot the global interrupts.
#define BTN_INFO_STRUCT_DEFAULT
Default button information structure btn_info_struct.
Definition button.h:171
static btn_info_struct btn_get_info(btn_info_t *const btn_info)
Actions before events proc.
static void btn_reset_atomic_fegi(btn_info_t *const btn_info)
Such as the btn_reset, but executed atomically with force enabling ot the global interrupts.
void btn_proc(btn_info_t *const btn_info, const bool is_now_hold)
Update counters and button press stages for a button information structure.
static void btn_proc_atomic(btn_info_t *const btn_info, const bool is_now_hold)
Such as the btn_proc, but executed atomically.
uint8_t byte_t
8-bit type
Definition defs.h:64
Information about a button.
Definition button.h:158
byte_t state
Stages and states flags of click processing.
Definition button.h:163
uint8_t _counter
Clamped or released state cycle counter.
Definition button.h:159
uint8_t _up_counter
Counter of cycles of released state after pressing.
Definition button.h:161