Skip to content

Refactoring and optimization #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions src/core/MultiButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,10 @@ class MultiButton : public VirtButton {
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);
if (!bf.read(EB_BOTH)) {
b0.call();
b1.call();
return VirtButton::tick(false);
}
return VirtButton::tick(b0, b1);
}
};
23 changes: 11 additions & 12 deletions src/core/VirtButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ enum class EBAction {
#define EB_HLD_R (1 << 2)
#define EB_STP_R (1 << 3)
#define EB_REL_R (1 << 4)
#define EB_ALL_R (EB_CLKS_R | EB_PRS_R | EB_HLD_R | EB_STP_R | EB_REL_R)

#define EB_PRS (1 << 5)
#define EB_HLD (1 << 6)
Expand Down Expand Up @@ -165,11 +166,9 @@ class VirtButton {

// принудительно сбросить флаги событий
void clear(bool resetTout = false) {
if (resetTout && bf.read(EB_TOUT)) bf.clear(EB_TOUT);
if (resetTout) bf.clear(EB_TOUT);
if (bf.read(EB_CLKS_R)) clicks = 0;
if (bf.read(EB_CLKS_R | EB_STP_R | EB_PRS_R | EB_HLD_R | EB_REL_R)) {
bf.clear(EB_CLKS_R | EB_STP_R | EB_PRS_R | EB_HLD_R | EB_REL_R);
}
bf.clear(EB_ALL_R);
}

// игнорировать все события до отпускания кнопки
Expand Down Expand Up @@ -206,7 +205,7 @@ class VirtButton {

// кнопка отпущена (в любом случае) [событие]
bool release() {
return bf.eq(EB_REL_R | EB_REL, EB_REL_R | EB_REL);
return bf.all(EB_REL_R | EB_REL);
}

// кнопка отпущена (в любом случае) с предварительными кликами [событие]
Expand Down Expand Up @@ -246,7 +245,7 @@ class VirtButton {

// кнопка удерживается (больше таймаута) [состояние]
bool holding() {
return bf.eq(EB_PRS | EB_HLD, EB_PRS | EB_HLD);
return bf.all(EB_PRS | EB_HLD);
}

// кнопка удерживается (больше таймаута) с предварительными кликами [состояние]
Expand Down Expand Up @@ -304,7 +303,7 @@ class VirtButton {

// кнопка отпущена после импульсного удержания с предварительными кликами [событие]
bool releaseStep(const uint8_t num) {
return clicks == num && bf.eq(EB_CLKS_R | EB_STP, EB_CLKS_R | EB_STP);
return clicks == num && bf.all(EB_CLKS_R | EB_STP);
}

// кнопка отпущена после удержания или импульсного удержания [событие]
Expand All @@ -319,7 +318,7 @@ class VirtButton {

// кнопка ожидает повторных кликов [состояние]
bool waiting() {
return clicks && bf.eq(EB_PRS | EB_REL, 0);
return clicks && !bf.read(EB_PRS | EB_REL);
}

// идёт обработка [состояние]
Expand All @@ -329,7 +328,7 @@ class VirtButton {

// было действие с кнопки, вернёт код события [событие]
uint16_t action() {
switch (bf.mask(0b111111111)) {
switch (bf.mask(EB_ALL_R | EB_PRS | EB_HLD | EB_STP | EB_REL)) {
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;
Expand Down Expand Up @@ -564,7 +563,7 @@ class VirtButton {
} else if (clicks) { // есть клики, ждём EB_CLICK_TIME
if (bf.read(EB_HLD | EB_STP) || deb >= EB_GET_CLICK_TIME()) bf.set(EB_CLKS_R); // флаг clicks
#ifndef EB_NO_FOR
else if (ftmr) ftmr = 0;
else ftmr = 0;
#endif
} else if (bf.read(EB_BUSY)) {
bf.clear(EB_HLD | EB_STP | EB_BUSY);
Expand All @@ -574,8 +573,8 @@ class VirtButton {
#endif
tmr = ms; // test!!
}
if (bf.read(EB_DEB)) bf.clear(EB_DEB); // сброс ожидания нажатия (дебаунс)
bf.clear(EB_DEB); // сброс ожидания нажатия (дебаунс)
}
return bf.read(EB_CLKS_R | EB_PRS_R | EB_HLD_R | EB_STP_R | EB_REL_R);
return bf.read(EB_ALL_R);
}
};
56 changes: 28 additions & 28 deletions src/core/VirtEncButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#define EB_FAST_T (EB_FAST_TIME)
#endif

#define EB_BUF_TURN (1 << 0)
#define EB_BUF_DIR (1 << 1)
#define EB_BUF_FAST (1 << 2)
#define EB_BUF_LEN 3

// базовый клас энкодера с кнопкой
class VirtEncButton : public VirtButton, public VirtEncoder {
public:
Expand Down Expand Up @@ -77,22 +82,19 @@ class VirtEncButton : public VirtButton, public VirtEncoder {
// обработка в прерывании (только энкодер). Вернёт 0 в покое, 1 или -1 при повороте
int8_t tickISR(const bool e0, const bool e1) {
int8_t state = VirtEncoder::pollEnc(e0, e1);
if (state) {
if (!state) return state;

#ifdef EB_NO_BUFFER
ef.set(EB_ISR_F);
ef.write(EB_DIR, state > 0);
ef.write(EB_FAST, _checkFast());
ef.set(EB_ISR_F);
ef.write(EB_DIR, state > 0);
ef.write(EB_FAST, _checkFast());
#else
for (uint8_t i = 0; i < 15; i += 3) {
if (!(ebuffer & (1 << i))) {
ebuffer |= (1 << i); // turn
if (state > 0) ebuffer |= (1 << (i + 1)); // dir
if (_checkFast()) ebuffer |= (1 << (i + 2)); // fast
break;
}
}
#endif
for (uint8_t i = 0; i < 15; i += EB_BUF_LEN) {
if (ebuffer & (EB_BUF_TURN << i)) continue;
ebuffer |= (EB_BUF_TURN | ((state > 0) * EB_BUF_DIR) | (_checkFast() * EB_BUF_FAST)) << i;
break;
}
#endif
return state;
}

Expand Down Expand Up @@ -133,7 +135,7 @@ class VirtEncButton : public VirtButton, public VirtEncoder {
private:
bool _checkFast() {
uint16_t ms = EB_uptime();
bool f = ms - tmr < EB_FAST_T;
bool f = (ms - tmr) < EB_FAST_T;
tmr = ms;
return f;
}
Expand All @@ -146,31 +148,29 @@ class VirtEncButton : public VirtButton, public VirtEncoder {
}

bool _tickRaw(bool btn, int8_t estate = 0) {
bool encf = 0;
#ifdef EB_NO_BUFFER
if (ef.read(EB_ISR_F)) {
ef.clear(EB_ISR_F);
encf = 1;
}
#else
if (ebuffer) {
ef.write(EB_DIR, ebuffer & 0b10);
ef.write(EB_FAST, ebuffer & 0b100);
ebuffer >>= 3;
encf = 1;
ef.write(EB_DIR, ebuffer & EB_BUF_DIR);
ef.write(EB_FAST, ebuffer & EB_BUF_FAST);
ebuffer >>= EB_BUF_LEN;
}
#endif
else if (estate) {
ef.write(EB_DIR, estate > 0);
ef.write(EB_FAST, _checkFast());
encf = 1;
}
if (encf) {
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); // флаг поворота
}
return VirtButton::tickRaw(btn) | encf;
else return VirtButton::tickRaw(btn);

if (bf.read(EB_PRS)) bf.set(EB_EHLD); // зажать энкодер
else clicks = 0;
bf.set(EB_TOUT); // таймаут
ef.set(EB_ETRN_R); // флаг поворота

VirtButton::tickRaw(btn);
return true;
}
};
70 changes: 32 additions & 38 deletions src/core/VirtEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define EB_STEP1 3

// ===================== FLAGS ======================
#define EB_TYPE (1 << 0)
#define EB_TYPE ((1 << 0) | (1 << 1))
#define EB_REV (1 << 2)
#define EB_FAST (1 << 3)
#define EB_DIR (1 << 4)
Expand All @@ -29,12 +29,13 @@ class VirtEncoder {
// ====================== SET ======================
// инвертировать направление энкодера
void setEncReverse(const bool rev) {
rev ? ef.set(EB_REV) : ef.clear(EB_REV);
ef.write(EB_REV, rev);
}

// установить тип энкодера (EB_STEP4_LOW, EB_STEP4_HIGH, EB_STEP2, EB_STEP1)
void setEncType(const uint8_t type) {
ef.flags = (ef.flags & 0b11111100) | type;
ef.clear(~EB_TYPE);
ef.set(type);
}

// использовать обработку энкодера в прерывании
Expand All @@ -49,7 +50,7 @@ class VirtEncoder {

// сбросить флаги событий
void clear() {
if (ef.read(EB_ETRN_R)) ef.clear(EB_ETRN_R);
ef.clear(EB_ETRN_R);
}

// ====================== ОПРОС ======================
Expand Down Expand Up @@ -96,51 +97,44 @@ class VirtEncoder {
int8_t state = tickRaw();
if (state) return state;

state = pollEnc(e0, e1);
if (state) {
ef.write(EB_DIR, state > 0);
ef.set(EB_ETRN_R);
}
return state;
return tickISR(e0, e1);
}

// опросить энкодер без сброса события поворота (сам опрос в прерывании)
int8_t tickRaw() {
if (ef.read(EB_ISR_F)) {
ef.clear(EB_ISR_F);
ef.set(EB_ETRN_R);
return dir();
}
return 0;
if (!ef.read(EB_ISR_F)) return 0;

ef.clear(EB_ISR_F);
ef.set(EB_ETRN_R);
return dir();
}

// POLL
// опросить энкодер без установки события поворота (быстрее). Вернёт 1 или -1 при вращении, 0 при остановке
int8_t pollEnc(const bool e0, const bool e1) {
if (p0 ^ p1 ^ e0 ^ e1) {
(p1 ^ e0) ? ++epos : --epos;
p0 = e0, p1 = e1;
if (!epos) return 0;

switch (ef.mask(0b11)) {
case EB_STEP4_LOW:
if (!(e0 & e1)) return 0; // skip 01, 10, 00
break;
case EB_STEP4_HIGH:
if (e0 | e1) return 0; // skip 01, 10, 11
break;
case EB_STEP2:
if (e0 ^ e1) return 0; // skip 10 01
break;
}
int8_t state = ((epos > 0) ^ ef.read(EB_REV)) ? -1 : 1;
epos = 0;
if (!(p0 ^ p1 ^ e0 ^ e1)) return 0;

(p1 ^ e0) ? ++epos : --epos;
p0 = e0, p1 = e1;
if (!epos) return 0;

switch (ef.mask(0b11)) {
case EB_STEP4_LOW:
if (!(e0 & e1)) return 0; // skip 01, 10, 00
break;
case EB_STEP4_HIGH:
if (e0 | e1) return 0; // skip 01, 10, 11
break;
case EB_STEP2:
if (e0 ^ e1) return 0; // skip 10 01
break;
}
int8_t state = ((epos > 0) ^ ef.read(EB_REV)) ? -1 : 1;
epos = 0;
#ifndef EB_NO_COUNTER
counter += state;
counter += state;
#endif
return state;
}
return 0;
return state;
}

#ifndef EB_NO_COUNTER
Expand Down
3 changes: 3 additions & 0 deletions src/core/flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ struct Flags {
inline bool eq(const T x, const T y) __attribute__((always_inline)) {
return (flags & x) == y;
}
inline bool all(const T x) __attribute__((always_inline)) {
return eq(x, x);
}
};

} // namespace encb