первый
This commit is contained in:
475
GyverEncoder.cpp
Normal file
475
GyverEncoder.cpp
Normal file
@@ -0,0 +1,475 @@
|
||||
#include "GyverEncoder.h"
|
||||
#include "mbed.h"
|
||||
#include <debounce.h>
|
||||
|
||||
#if defined(PRECISE_ALGORITHM)
|
||||
const int8_t KNOBDIR[] = {
|
||||
0,
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
-1,
|
||||
0,
|
||||
};
|
||||
int8_t encPos = 0;
|
||||
#endif
|
||||
|
||||
// ================= CONSTRUCTOR =================
|
||||
Encoder::Encoder()
|
||||
{
|
||||
flags.use_button = true;
|
||||
}
|
||||
|
||||
Encoder::Encoder(PinName clk, PinName dt, PinName sw, bool type)
|
||||
{
|
||||
|
||||
if (sw != NC) {
|
||||
_SW = new DigitalIn(sw, PullUp);
|
||||
flags.use_button = true;
|
||||
} else {
|
||||
flags.use_button = false;
|
||||
}
|
||||
flags.enc_type = type;
|
||||
|
||||
_CLK = new DigitalIn(clk, PullUp);
|
||||
_DT = new DigitalIn(dt, PullUp);
|
||||
|
||||
flags.invBtn = (DEFAULT_BTN_PULL == HIGH_PULL) ? true : false;
|
||||
|
||||
#if defined(FAST_ALGORITHM)
|
||||
prevState = digitalRead(_CLK);
|
||||
#else
|
||||
prevState = (_CLK->read() | _DT->read() << 1);
|
||||
#endif
|
||||
|
||||
flags.isDouble_f = false;
|
||||
flags.isPress_f = false;
|
||||
flags.isRelease_f = false;
|
||||
flags.isHolded_f = false;
|
||||
flags.butt_flag = false;
|
||||
flags.hold_flag = false;
|
||||
|
||||
debounce_timer = Kernel::Clock::now();
|
||||
|
||||
encThread = new Thread(osPriorityNormal, 1024, NULL, "Encoder Thread");
|
||||
}
|
||||
|
||||
void Encoder::start()
|
||||
{
|
||||
// _CLK->fall(callback(this, &Encoder::encoderThread));
|
||||
// _CLK->rise(callback(this, &Encoder::encoderThread));
|
||||
|
||||
// _SW->fall(callback(this, &Encoder::encoderThread));
|
||||
// _SW->rise(callback(this, &Encoder::encoderThread));
|
||||
encThread->start(callback(this, &Encoder::encoderThread));
|
||||
}
|
||||
|
||||
void Encoder::stop()
|
||||
{
|
||||
encThread->terminate();
|
||||
}
|
||||
|
||||
void Encoder::encoderThread()
|
||||
{
|
||||
|
||||
for (;;) {
|
||||
this->tick();
|
||||
|
||||
ThisThread::sleep_for(1ms);
|
||||
}
|
||||
}
|
||||
|
||||
// ================= SET =================
|
||||
void Encoder::setDirection(bool direction)
|
||||
{
|
||||
if (direction) {
|
||||
// uint8_t buf = _CLK;
|
||||
// _CLK = _DT;
|
||||
// _DT = buf;
|
||||
}
|
||||
}
|
||||
void Encoder::setPinMode(bool mode)
|
||||
{
|
||||
_CLK->mode((mode) ? PullDown : PullUp);
|
||||
_DT->mode((mode) ? PullDown : PullUp);
|
||||
}
|
||||
void Encoder::setBtnPinMode(bool mode)
|
||||
{
|
||||
|
||||
_SW->mode((mode) ? PullDown : PullUp);
|
||||
flags.invBtn = (mode) ? 0 : 1;
|
||||
}
|
||||
void Encoder::setType(bool type)
|
||||
{
|
||||
flags.enc_type = type;
|
||||
}
|
||||
void Encoder::setTickMode(bool tickMode)
|
||||
{
|
||||
flags.enc_tick_mode = tickMode;
|
||||
}
|
||||
void Encoder::setFastTimeout(Kernel::Clock::duration timeout)
|
||||
{
|
||||
_fast_timeout = timeout;
|
||||
}
|
||||
|
||||
// ================= IS =================
|
||||
// повороты
|
||||
bool Encoder::isTurn()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isTurn_f) {
|
||||
flags.isTurn_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isRight()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 2) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isLeft()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 1) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isRightH()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 4) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isLeftH()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (encState == 3) {
|
||||
encState = 0;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isFastR()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isFastR_f) {
|
||||
flags.isFastR_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isFastL()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isFastL_f) {
|
||||
flags.isFastL_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
// кнопка
|
||||
bool Encoder::isPress()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isPress_f) {
|
||||
flags.isPress_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isRelease()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isRelease_f) {
|
||||
flags.isRelease_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isClick()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isRelease_f) {
|
||||
flags.isRelease_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isHolded()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.hold_flag && flags.isHolded_f) {
|
||||
flags.isHolded_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isSingle()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
if (flags.isSingle_f) {
|
||||
flags.isSingle_f = false;
|
||||
flags.isDouble_f = false;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isDouble()
|
||||
{
|
||||
// if (flags.enc_tick_mode)
|
||||
// Encoder::tick();
|
||||
// if (flags.isDouble_f)
|
||||
// {
|
||||
// flags.isDouble_f = false;
|
||||
// flags.isSingle_f = false;
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// return false;
|
||||
if (flags.isDouble_f) {
|
||||
flags.isDouble_f = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Encoder::isHold()
|
||||
{
|
||||
if (flags.enc_tick_mode)
|
||||
Encoder::tick();
|
||||
return (SW_state);
|
||||
}
|
||||
|
||||
// ================= TICK =================
|
||||
void Encoder::tick(bool clk, bool dt, bool sw)
|
||||
{
|
||||
extTick = true;
|
||||
flags.extCLK = clk;
|
||||
flags.extDT = dt;
|
||||
flags.extSW = sw;
|
||||
Encoder::tick();
|
||||
extTick = false;
|
||||
}
|
||||
|
||||
void Encoder::tick()
|
||||
{
|
||||
thisMls = Kernel::Clock::now();
|
||||
debounceDelta = thisMls - debounce_timer;
|
||||
// int butstate;
|
||||
|
||||
#ifdef ENC_WITH_BUTTON
|
||||
// static etl::debounce<DEBOUNCE_COUNT, HOLD_COUNT, REPEAT_COUNT> key_state;
|
||||
// static etl::debounce<DEBOUNCE_COUNT, HOLD_COUNT, REPEAT_COUNT> key_invState;
|
||||
// // butstate = *_SW;
|
||||
|
||||
// if (key_state.add(*_SW == 0)) {
|
||||
// if (key_state.is_set() && flags.isRelease_f == true) {
|
||||
// flags.isPress_f = true;
|
||||
// flags.butt_flag = true;
|
||||
// flags.isRelease_f = false;
|
||||
// }
|
||||
// if (key_state.is_held()) {
|
||||
// flags.isHolded_f = true;
|
||||
// flags.butt_flag = false;
|
||||
|
||||
// } else
|
||||
|
||||
// if (key_state.is_repeating()) {
|
||||
// flags.isDouble_f = true;
|
||||
// }
|
||||
// }
|
||||
// // if (flags.butt_flag) {
|
||||
// if (key_invState.add(*_SW == 1)) {
|
||||
// if (key_invState.is_set()) {
|
||||
// flags.isPress_f = false;
|
||||
// flags.isRelease_f = true;
|
||||
// flags.butt_flag = false;
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (flags.use_button) {
|
||||
if (!extTick)
|
||||
// if (_SW->read() == 0) { // читаем состояние кнопки SW
|
||||
SW_state = _SW->read() ^ flags.invBtn;
|
||||
// } else {
|
||||
// SW_state = false ^ flags.invBtn;
|
||||
// }
|
||||
else
|
||||
SW_state = flags.extSW;
|
||||
|
||||
if (SW_state && !flags.butt_flag && (debounceDelta > ENC_DEBOUNCE_BUTTON)) {
|
||||
flags.butt_flag = true;
|
||||
flags.turn_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
flags.isPress_f = true;
|
||||
flags.isHolded_f = true;
|
||||
flags.doubleAllow = true;
|
||||
}
|
||||
if (!SW_state && flags.butt_flag && (debounceDelta > ENC_DEBOUNCE_BUTTON)) {
|
||||
if (!flags.turn_flag && !flags.hold_flag) { // если кнопка отпущена и ручка не поворачивалась
|
||||
flags.turn_flag = false;
|
||||
flags.isRelease_f = true;
|
||||
}
|
||||
if (debounceDelta > ENC_HOLD_TIMEOUT)
|
||||
flags.isReleaseHold_f = true;
|
||||
flags.butt_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
flags.hold_flag = false;
|
||||
|
||||
if (flags.doubleAllow && !flags.doubleFlag) {
|
||||
flags.doubleFlag = true;
|
||||
flags.countFlag = false;
|
||||
} else {
|
||||
flags.countFlag = true;
|
||||
}
|
||||
}
|
||||
if (flags.doubleFlag && debounceDelta > ENC_DOUBLE_TIMEOUT) {
|
||||
if (!flags.turn_flag) {
|
||||
if (!flags.countFlag)
|
||||
flags.isSingle_f = true;
|
||||
else
|
||||
flags.isDouble_f = true;
|
||||
}
|
||||
flags.doubleFlag = false;
|
||||
}
|
||||
if (flags.butt_flag && debounceDelta > ENC_HOLD_TIMEOUT && !flags.turn_flag) {
|
||||
if (SW_state) {
|
||||
flags.hold_flag = true;
|
||||
flags.doubleAllow = false;
|
||||
} else {
|
||||
flags.butt_flag = false;
|
||||
flags.hold_flag = false;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FAST_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK) : (digitalRead(_CLK));
|
||||
|
||||
if (curState != prevState
|
||||
#if (ENC_DEBOUNCE_TURN > 0)
|
||||
&& (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
#endif
|
||||
) {
|
||||
encState = 0;
|
||||
turnFlag = !turnFlag;
|
||||
if (turnFlag || !flags.enc_type) {
|
||||
if (((extTick) ? (flags.extDT) : digitalRead(_DT)) != prevState) {
|
||||
encState = 1;
|
||||
} else {
|
||||
encState = 2;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(BINARY_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK | (flags.extDT << 1)) : (_CLK->read() | (_DT->read() << 1));
|
||||
|
||||
if (curState != prevState
|
||||
//#if (ENC_DEBOUNCE_TURN > 0)
|
||||
&& (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
//#endif
|
||||
) {
|
||||
encState = 0;
|
||||
if (curState == 0b11) {
|
||||
switch (prevState) {
|
||||
case 0b10:
|
||||
encState = 1;
|
||||
break;
|
||||
case 0b01:
|
||||
encState = 2;
|
||||
break;
|
||||
}
|
||||
} else if (curState == 0b00 && !flags.enc_type) {
|
||||
switch (prevState) {
|
||||
case 0b01:
|
||||
encState = 1;
|
||||
break;
|
||||
case 0b10:
|
||||
encState = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(PRECISE_ALGORITHM)
|
||||
uint8_t curState = (extTick) ? (flags.extCLK | (flags.extDT << 1)) : (_CLK->read() | (_DT->read() << 1));
|
||||
|
||||
if (prevState != curState
|
||||
//#if (ENC_DEBOUNCE_TURN > 0)
|
||||
// && (debounceDelta > ENC_DEBOUNCE_TURN)
|
||||
//#endif
|
||||
) {
|
||||
encState = 0;
|
||||
encPos += KNOBDIR[curState | (prevState << 2)];
|
||||
if (flags.enc_type) {
|
||||
if (curState == 0x3 && encPos != 0) {
|
||||
encState = (encPos == 4) ? 1 : 2;
|
||||
encPos = 0;
|
||||
}
|
||||
} else {
|
||||
if ((curState == 0x3 || !curState) && encPos != 0) {
|
||||
encState = (encPos == 2) ? 1 : 2;
|
||||
encPos = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (encState != 0) {
|
||||
flags.isTurn_f = true;
|
||||
if (thisMls - fast_timer < _fast_timeout) {
|
||||
if (encState == 1)
|
||||
flags.isFastL_f = true;
|
||||
else if (encState == 2)
|
||||
flags.isFastR_f = true;
|
||||
fast_timer = thisMls;
|
||||
} else
|
||||
fast_timer = thisMls;
|
||||
#ifdef ENC_WITH_BUTTON
|
||||
// if (flags.use_button)
|
||||
// if (SW_state)
|
||||
// encState += 2;
|
||||
#endif
|
||||
}
|
||||
prevState = curState;
|
||||
flags.turn_flag = true;
|
||||
debounce_timer = thisMls;
|
||||
debounceDelta = 0ms;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user