Skip to content

Commit 948c125

Browse files
committed
upd
1 parent 164471b commit 948c125

File tree

9 files changed

+187
-44
lines changed

9 files changed

+187
-44
lines changed

README.md

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,9 @@ void setDebTimeout(uint8_t tout);
269269
// умолч. HIGH, то есть true - кнопка нажата
270270
void setBtnLevel(bool level);
271271
272-
// подключить функцию-обработчик событий (вида void f())
272+
// подключить функцию-обработчик событий
273273
void attach(void (*handler)());
274+
void attach(void (*handler)(void* self));
274275
275276
// отключить функцию-обработчик событий
276277
void detach();
@@ -1061,26 +1062,50 @@ void loop() {
10611062
}
10621063
```
10631064
1065+
С версии 3.6.0 библиотека поддерживает подключение обработчика с отправкой в него указателя на объект:
1066+
```cpp
1067+
EncButton eb(2, 3, 4);
1068+
1069+
void callback(void* self) {
1070+
EncButton& enc = *static_cast<EncButton*>(self);
1071+
1072+
switch (enc.action()) {
1073+
case EB_PRESS:
1074+
// ...
1075+
break;
1076+
case EB_HOLD:
1077+
// ...
1078+
break;
1079+
// ...
1080+
}
1081+
}
1082+
1083+
void setup() {
1084+
eb.attach(callback);
1085+
}
1086+
1087+
void loop() {
1088+
eb.tick();
1089+
}
1090+
```
1091+
10641092
<a id="double"></a>
10651093

10661094
### Одновременное нажатие
10671095
Библиотека нативно поддерживает работу с двумя одновременно нажатыми кнопками как с третьей кнопкой. Для этого нужно:
1068-
1. Cоздать виртуальную кнопку `VirtButton`
1069-
2. Вызвать обработку реальных кнопок
1070-
3. Передать виртуальной кнопке в обработку эти кнопки (это могут быть объекты классов `VirtButton`, `Button`, `EncButton` + их `T`-версии)
1071-
4. Далее опрашивать события
1096+
1. Cоздать специальную кнопку `MultiButton`
1097+
2. Передать виртуальной кнопке в обработку свои кнопки (это могут быть объекты классов `VirtButton`, `Button`, `EncButton` + их `T`-версии). **Мульти-кнопка сама опросит обе кнопки!**
1098+
3. Опрашивать события или слушать обработчик
10721099

10731100
```cpp
10741101
Button b0(4);
10751102
Button b1(5);
1076-
VirtButton b2; // 1
1103+
MultiButton b2; // 1
10771104

10781105
void loop() {
1079-
b0.tick(); // 2
1080-
b1.tick(); // 2
1081-
b2.tick(b0, b1); // 3
1106+
b2.tick(b0, b1); // 2
10821107

1083-
// 4
1108+
// 3
10841109
if (b0.click()) Serial.println("b0 click");
10851110
if (b1.click()) Serial.println("b1 click");
10861111
if (b2.click()) Serial.println("b0+b1 click");
@@ -1792,7 +1817,10 @@ void loop() {
17921817
- v3.5.5 - коллбэк на базе std::function для ESP
17931818
- v3.5.8 - добавлен метод releaseHoldStep()
17941819
- v3.5.11 - добавлен метод skipEvents() для игнорирования событий кнопки в сложных сценариях использования
1795-
1820+
- v3.6.0
1821+
- Добавлен класс MultiButton для корректного опроса нескольких кнопок с вызовом обработчика
1822+
- Добавлено подключение обработчика с передачей указателя на объект
1823+
17961824
<a id="feedback"></a>
17971825
## Баги и обратная связь
17981826
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [[email protected]](mailto:[email protected])
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// опрос одновременного нажатия двух кнопок как нажатия третьей кнопки
2+
// с корректным вызовом обработчиков
3+
4+
#include <Arduino.h>
5+
#include <EncButton.h>
6+
7+
Button b0(4);
8+
Button b1(5);
9+
MultiButton b2; // виртуальная
10+
11+
void decode(uint16_t action) {
12+
switch (action) {
13+
case EB_PRESS:
14+
Serial.println("press");
15+
break;
16+
case EB_STEP:
17+
Serial.println("step");
18+
break;
19+
case EB_RELEASE:
20+
Serial.println("release");
21+
break;
22+
case EB_CLICK:
23+
Serial.println("click");
24+
break;
25+
case EB_CLICKS:
26+
Serial.print("clicks");
27+
break;
28+
case EB_REL_HOLD:
29+
Serial.println("release hold");
30+
break;
31+
case EB_REL_HOLD_C:
32+
Serial.print("release hold clicks ");
33+
break;
34+
case EB_REL_STEP:
35+
Serial.println("release step");
36+
break;
37+
case EB_REL_STEP_C:
38+
Serial.print("release step clicks ");
39+
break;
40+
}
41+
}
42+
43+
void setup() {
44+
Serial.begin(115200);
45+
46+
// обработчики
47+
b0.attach([](void* b) {
48+
uint16_t action = static_cast<VirtButton*>(b)->action();
49+
if (action != EB_HOLD) Serial.println("b0");
50+
decode(action);
51+
});
52+
53+
b1.attach([](void* b) {
54+
uint16_t action = static_cast<VirtButton*>(b)->action();
55+
if (action != EB_HOLD) Serial.println("b1");
56+
decode(action);
57+
});
58+
59+
b2.attach([](void* b) {
60+
uint16_t action = static_cast<VirtButton*>(b)->action();
61+
if (action != EB_HOLD) Serial.println("b2");
62+
decode(action);
63+
});
64+
}
65+
66+
void loop() {
67+
// обработка одновременного нажатия двух кнопок
68+
// обрабатываются все три кнопки
69+
b2.tick(b0, b1);
70+
71+
// или вручную
72+
if (b0.click()) Serial.println("b0 click");
73+
if (b1.click()) Serial.println("b1 click");
74+
if (b2.click()) Serial.println("b0+b1 click");
75+
}

keywords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Button KEYWORD1
1212
ButtonT KEYWORD1
1313
VirtEncoder KEYWORD1
1414
VirtButton KEYWORD1
15+
MultiButton KEYWORD1
1516

1617
EB_NO_COUNTER KEYWORD1
1718
EB_NO_BUFFER KEYWORD1

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=EncButton
2-
version=3.5.11
2+
version=3.6.0
33
author=AlexGyver <[email protected]>
44
maintainer=AlexGyver <[email protected]>
55
sentence=Light and powerful library for button and encoder operation for Arduino

src/EncButton.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#pragma once
22
#include <Arduino.h>
33

4-
#include "core/VirtButton.h"
5-
#include "core/VirtEncoder.h"
6-
#include "core/VirtEncButton.h"
74
#include "core/Button.h"
5+
#include "core/EncButton.h"
86
#include "core/Encoder.h"
9-
#include "core/EncButton.h"
7+
#include "core/MultiButton.h"
8+
#include "core/VirtButton.h"
9+
#include "core/VirtEncButton.h"
10+
#include "core/VirtEncoder.h"

src/core/MultiButton.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
#include <Arduino.h>
3+
4+
#include "VirtButton.h"
5+
6+
class MultiButton : public VirtButton {
7+
public:
8+
template <typename T0, typename T1>
9+
bool tick(T0& b0, T1& b1) {
10+
b0.clear();
11+
b1.clear();
12+
b0.tickRaw();
13+
b1.tickRaw();
14+
15+
if (bf.read(EB_BOTH)) {
16+
if (!b0.pressing() && !b1.pressing()) bf.clear(EB_BOTH);
17+
if (!b0.pressing()) b0.reset();
18+
if (!b1.pressing()) b1.reset();
19+
b0.clear();
20+
b1.clear();
21+
return VirtButton::tick(true);
22+
} else {
23+
if (b0.pressing() && b1.pressing()) bf.set(EB_BOTH);
24+
b0.call();
25+
b1.call();
26+
return VirtButton::tick(false);
27+
}
28+
}
29+
};

src/core/VirtButton.h

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@
6969
class VirtButton {
7070
#ifdef __AVR__
7171
typedef void (*ActionHandler)();
72+
typedef void (*ActionHandlerThis)(void*);
7273
#else
7374
typedef std::function<void()> ActionHandler;
75+
typedef std::function<void(void*)> ActionHandlerThis;
7476
#endif
7577

7678
public:
@@ -140,10 +142,18 @@ class VirtButton {
140142
#endif
141143
}
142144

145+
// подключить функцию-обработчик событий (вида void f(void*))
146+
void attach(ActionHandlerThis handler) {
147+
#ifndef EB_NO_CALLBACK
148+
cbt = handler;
149+
#endif
150+
}
151+
143152
// отключить функцию-обработчик событий
144153
void detach() {
145154
#ifndef EB_NO_CALLBACK
146155
cb = nullptr;
156+
cbt = nullptr;
147157
#endif
148158
}
149159

@@ -288,28 +298,19 @@ class VirtButton {
288298
// было действие с кнопки, вернёт код события [событие]
289299
uint16_t action() {
290300
switch (bf.mask(0b111111111)) {
291-
case (EB_PRS | EB_PRS_R):
292-
return EB_PRESS;
293-
case (EB_PRS | EB_HLD | EB_HLD_R):
294-
return EB_HOLD;
295-
case (EB_PRS | EB_HLD | EB_STP | EB_STP_R):
296-
return EB_STEP;
301+
case (EB_PRS | EB_PRS_R): return EB_PRESS;
302+
case (EB_PRS | EB_HLD | EB_HLD_R): return EB_HOLD;
303+
case (EB_PRS | EB_HLD | EB_STP | EB_STP_R): return EB_STEP;
297304
case (EB_REL | EB_REL_R):
298305
case (EB_REL | EB_REL_R | EB_HLD):
299306
case (EB_REL | EB_REL_R | EB_HLD | EB_STP):
300307
return EB_RELEASE;
301-
case (EB_REL_R):
302-
return EB_CLICK;
303-
case (EB_CLKS_R):
304-
return EB_CLICKS;
305-
case (EB_REL_R | EB_HLD):
306-
return EB_REL_HOLD;
307-
case (EB_CLKS_R | EB_HLD):
308-
return EB_REL_HOLD_C;
309-
case (EB_REL_R | EB_HLD | EB_STP):
310-
return EB_REL_STEP;
311-
case (EB_CLKS_R | EB_HLD | EB_STP):
312-
return EB_REL_STEP_C;
308+
case (EB_REL_R): return EB_CLICK;
309+
case (EB_CLKS_R): return EB_CLICKS;
310+
case (EB_REL_R | EB_HLD): return EB_REL_HOLD;
311+
case (EB_CLKS_R | EB_HLD): return EB_REL_HOLD_C;
312+
case (EB_REL_R | EB_HLD | EB_STP): return EB_REL_STEP;
313+
case (EB_CLKS_R | EB_HLD | EB_STP): return EB_REL_STEP_C;
313314
}
314315
return 0;
315316
}
@@ -395,9 +396,7 @@ class VirtButton {
395396
bool tick(bool s) {
396397
clear();
397398
s = pollBtn(s);
398-
#ifndef EB_NO_CALLBACK
399-
if (cb && s) cb();
400-
#endif
399+
if (s) call();
401400
return s;
402401
}
403402

@@ -406,6 +405,14 @@ class VirtButton {
406405
return pollBtn(s);
407406
}
408407

408+
// вызвать обработчик
409+
void call() {
410+
if (action()) {
411+
if (cb) cb();
412+
if (cbt) cbt(this);
413+
}
414+
}
415+
409416
uint8_t clicks;
410417

411418
// deprecated
@@ -420,6 +427,7 @@ class VirtButton {
420427

421428
#ifndef EB_NO_CALLBACK
422429
ActionHandler cb = nullptr;
430+
ActionHandlerThis cbt = nullptr;
423431
#endif
424432

425433
private:

src/core/VirtEncButton.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,7 @@ class VirtEncButton : public VirtButton, public VirtEncoder {
107107
bool tick(const int8_t state, const bool btn) {
108108
clear();
109109
bool f = tickRaw(state, btn);
110-
111-
#ifndef EB_NO_CALLBACK
112-
if (cb && f) cb();
113-
#endif
110+
if (f) call();
114111
return f;
115112
}
116113

@@ -149,7 +146,7 @@ class VirtEncButton : public VirtButton, public VirtEncoder {
149146
encf = 1;
150147
}
151148
if (encf) {
152-
if (bf.read(EB_PRS)) bf.set(EB_EHLD); // зажать энкодер
149+
if (bf.read(EB_PRS)) bf.set(EB_EHLD); // зажать энкодер
153150
else clicks = 0;
154151
if (!bf.read(EB_TOUT)) bf.set(EB_TOUT); // таймаут
155152
ef.set(EB_ETRN_R); // флаг поворота

src/core/VirtEncoder.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#pragma once
22
#include <Arduino.h>
33

4-
#include "io.h"
54
#include "flags.h"
5+
#include "io.h"
66

77
// ===================== CONST ======================
88
#define EB_STEP4_LOW 0
@@ -139,7 +139,11 @@ class VirtEncoder {
139139
// опросить энкодер без установки события поворота (быстрее). Вернёт 1 или -1 при вращении, 0 при остановке
140140
int8_t pollEnc(int8_t state) {
141141
if (prev != state) {
142-
ecount += ((0x49941661 >> ((state | (prev << 2)) << 1)) & 0b11) - 1;
142+
ecount += ((0x49941661 >> ((state | (prev << 2)) << 1)) & 0b11) - 1; // faster
143+
// switch (state | (prev << 2)) {
144+
// case 2: case 4: case 11: case 13: ecount++; break;
145+
// case 1: case 7: case 8: case 14: ecount--; break;
146+
// }
143147
prev = state;
144148
if (!ecount) return 0;
145149
switch (ef.mask(0b11)) {

0 commit comments

Comments
 (0)