Skip to content

Commit

Permalink
upd
Browse files Browse the repository at this point in the history
  • Loading branch information
GyverLibs committed Aug 26, 2024
1 parent 164471b commit 948c125
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 44 deletions.
50 changes: 39 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ void setDebTimeout(uint8_t tout);
// умолч. HIGH, то есть true - кнопка нажата
void setBtnLevel(bool level);
// подключить функцию-обработчик событий (вида void f())
// подключить функцию-обработчик событий
void attach(void (*handler)());
void attach(void (*handler)(void* self));
// отключить функцию-обработчик событий
void detach();
Expand Down Expand Up @@ -1061,26 +1062,50 @@ void loop() {
}
```
С версии 3.6.0 библиотека поддерживает подключение обработчика с отправкой в него указателя на объект:
```cpp
EncButton eb(2, 3, 4);
void callback(void* self) {
EncButton& enc = *static_cast<EncButton*>(self);
switch (enc.action()) {
case EB_PRESS:
// ...
break;
case EB_HOLD:
// ...
break;
// ...
}
}
void setup() {
eb.attach(callback);
}
void loop() {
eb.tick();
}
```

<a id="double"></a>

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

```cpp
Button b0(4);
Button b1(5);
VirtButton b2; // 1
MultiButton b2; // 1

void loop() {
b0.tick(); // 2
b1.tick(); // 2
b2.tick(b0, b1); // 3
b2.tick(b0, b1); // 2

// 4
// 3
if (b0.click()) Serial.println("b0 click");
if (b1.click()) Serial.println("b1 click");
if (b2.click()) Serial.println("b0+b1 click");
Expand Down Expand Up @@ -1792,7 +1817,10 @@ void loop() {
- v3.5.5 - коллбэк на базе std::function для ESP
- v3.5.8 - добавлен метод releaseHoldStep()
- v3.5.11 - добавлен метод skipEvents() для игнорирования событий кнопки в сложных сценариях использования
- v3.6.0
- Добавлен класс MultiButton для корректного опроса нескольких кнопок с вызовом обработчика
- Добавлено подключение обработчика с передачей указателя на объект
<a id="feedback"></a>
## Баги и обратная связь
При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [[email protected]](mailto:[email protected])
Expand Down
75 changes: 75 additions & 0 deletions examples/doubleCallback/doubleCallback.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// опрос одновременного нажатия двух кнопок как нажатия третьей кнопки
// с корректным вызовом обработчиков

#include <Arduino.h>
#include <EncButton.h>

Button b0(4);
Button b1(5);
MultiButton b2; // виртуальная

void decode(uint16_t action) {
switch (action) {
case EB_PRESS:
Serial.println("press");
break;
case EB_STEP:
Serial.println("step");
break;
case EB_RELEASE:
Serial.println("release");
break;
case EB_CLICK:
Serial.println("click");
break;
case EB_CLICKS:
Serial.print("clicks");
break;
case EB_REL_HOLD:
Serial.println("release hold");
break;
case EB_REL_HOLD_C:
Serial.print("release hold clicks ");
break;
case EB_REL_STEP:
Serial.println("release step");
break;
case EB_REL_STEP_C:
Serial.print("release step clicks ");
break;
}
}

void setup() {
Serial.begin(115200);

// обработчики
b0.attach([](void* b) {
uint16_t action = static_cast<VirtButton*>(b)->action();
if (action != EB_HOLD) Serial.println("b0");
decode(action);
});

b1.attach([](void* b) {
uint16_t action = static_cast<VirtButton*>(b)->action();
if (action != EB_HOLD) Serial.println("b1");
decode(action);
});

b2.attach([](void* b) {
uint16_t action = static_cast<VirtButton*>(b)->action();
if (action != EB_HOLD) Serial.println("b2");
decode(action);
});
}

void loop() {
// обработка одновременного нажатия двух кнопок
// обрабатываются все три кнопки
b2.tick(b0, b1);

// или вручную
if (b0.click()) Serial.println("b0 click");
if (b1.click()) Serial.println("b1 click");
if (b2.click()) Serial.println("b0+b1 click");
}
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Button KEYWORD1
ButtonT KEYWORD1
VirtEncoder KEYWORD1
VirtButton KEYWORD1
MultiButton KEYWORD1

EB_NO_COUNTER KEYWORD1
EB_NO_BUFFER KEYWORD1
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=EncButton
version=3.5.11
version=3.6.0
author=AlexGyver <[email protected]>
maintainer=AlexGyver <[email protected]>
sentence=Light and powerful library for button and encoder operation for Arduino
Expand Down
9 changes: 5 additions & 4 deletions src/EncButton.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once
#include <Arduino.h>

#include "core/VirtButton.h"
#include "core/VirtEncoder.h"
#include "core/VirtEncButton.h"
#include "core/Button.h"
#include "core/EncButton.h"
#include "core/Encoder.h"
#include "core/EncButton.h"
#include "core/MultiButton.h"
#include "core/VirtButton.h"
#include "core/VirtEncButton.h"
#include "core/VirtEncoder.h"
29 changes: 29 additions & 0 deletions src/core/MultiButton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once
#include <Arduino.h>

#include "VirtButton.h"

class MultiButton : public VirtButton {
public:
template <typename T0, typename T1>
bool tick(T0& b0, T1& b1) {
b0.clear();
b1.clear();
b0.tickRaw();
b1.tickRaw();

if (bf.read(EB_BOTH)) {
if (!b0.pressing() && !b1.pressing()) bf.clear(EB_BOTH);
if (!b0.pressing()) b0.reset();
if (!b1.pressing()) b1.reset();
b0.clear();
b1.clear();
return VirtButton::tick(true);
} else {
if (b0.pressing() && b1.pressing()) bf.set(EB_BOTH);
b0.call();
b1.call();
return VirtButton::tick(false);
}
}
};
50 changes: 29 additions & 21 deletions src/core/VirtButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@
class VirtButton {
#ifdef __AVR__
typedef void (*ActionHandler)();
typedef void (*ActionHandlerThis)(void*);
#else
typedef std::function<void()> ActionHandler;
typedef std::function<void(void*)> ActionHandlerThis;
#endif

public:
Expand Down Expand Up @@ -140,10 +142,18 @@ class VirtButton {
#endif
}

// подключить функцию-обработчик событий (вида void f(void*))
void attach(ActionHandlerThis handler) {
#ifndef EB_NO_CALLBACK
cbt = handler;
#endif
}

// отключить функцию-обработчик событий
void detach() {
#ifndef EB_NO_CALLBACK
cb = nullptr;
cbt = nullptr;
#endif
}

Expand Down Expand Up @@ -288,28 +298,19 @@ class VirtButton {
// было действие с кнопки, вернёт код события [событие]
uint16_t action() {
switch (bf.mask(0b111111111)) {
case (EB_PRS | EB_PRS_R):
return EB_PRESS;
case (EB_PRS | EB_HLD | EB_HLD_R):
return EB_HOLD;
case (EB_PRS | EB_HLD | EB_STP | EB_STP_R):
return EB_STEP;
case (EB_PRS | EB_PRS_R): return EB_PRESS;
case (EB_PRS | EB_HLD | EB_HLD_R): return EB_HOLD;
case (EB_PRS | EB_HLD | EB_STP | EB_STP_R): return EB_STEP;
case (EB_REL | EB_REL_R):
case (EB_REL | EB_REL_R | EB_HLD):
case (EB_REL | EB_REL_R | EB_HLD | EB_STP):
return EB_RELEASE;
case (EB_REL_R):
return EB_CLICK;
case (EB_CLKS_R):
return EB_CLICKS;
case (EB_REL_R | EB_HLD):
return EB_REL_HOLD;
case (EB_CLKS_R | EB_HLD):
return EB_REL_HOLD_C;
case (EB_REL_R | EB_HLD | EB_STP):
return EB_REL_STEP;
case (EB_CLKS_R | EB_HLD | EB_STP):
return EB_REL_STEP_C;
case (EB_REL_R): return EB_CLICK;
case (EB_CLKS_R): return EB_CLICKS;
case (EB_REL_R | EB_HLD): return EB_REL_HOLD;
case (EB_CLKS_R | EB_HLD): return EB_REL_HOLD_C;
case (EB_REL_R | EB_HLD | EB_STP): return EB_REL_STEP;
case (EB_CLKS_R | EB_HLD | EB_STP): return EB_REL_STEP_C;
}
return 0;
}
Expand Down Expand Up @@ -395,9 +396,7 @@ class VirtButton {
bool tick(bool s) {
clear();
s = pollBtn(s);
#ifndef EB_NO_CALLBACK
if (cb && s) cb();
#endif
if (s) call();
return s;
}

Expand All @@ -406,6 +405,14 @@ class VirtButton {
return pollBtn(s);
}

// вызвать обработчик
void call() {
if (action()) {
if (cb) cb();
if (cbt) cbt(this);
}
}

uint8_t clicks;

// deprecated
Expand All @@ -420,6 +427,7 @@ class VirtButton {

#ifndef EB_NO_CALLBACK
ActionHandler cb = nullptr;
ActionHandlerThis cbt = nullptr;
#endif

private:
Expand Down
7 changes: 2 additions & 5 deletions src/core/VirtEncButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,7 @@ class VirtEncButton : public VirtButton, public VirtEncoder {
bool tick(const int8_t state, const bool btn) {
clear();
bool f = tickRaw(state, btn);

#ifndef EB_NO_CALLBACK
if (cb && f) cb();
#endif
if (f) call();
return f;
}

Expand Down Expand Up @@ -149,7 +146,7 @@ class VirtEncButton : public VirtButton, public VirtEncoder {
encf = 1;
}
if (encf) {
if (bf.read(EB_PRS)) bf.set(EB_EHLD); // зажать энкодер
if (bf.read(EB_PRS)) bf.set(EB_EHLD); // зажать энкодер
else clicks = 0;
if (!bf.read(EB_TOUT)) bf.set(EB_TOUT); // таймаут
ef.set(EB_ETRN_R); // флаг поворота
Expand Down
8 changes: 6 additions & 2 deletions src/core/VirtEncoder.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once
#include <Arduino.h>

#include "io.h"
#include "flags.h"
#include "io.h"

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

0 comments on commit 948c125

Please sign in to comment.