436 lines
10 KiB
C++
Executable File
436 lines
10 KiB
C++
Executable File
#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.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
|
|
|
|
if (flags.use_button) {
|
|
if (!extTick)
|
|
SW_state = _SW->read() ^ 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) { // если кнопка отпущена и ручка не поворачивалась
|
|
if (!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;
|
|
flags.isRelease_f = 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;
|
|
}
|
|
}
|