Files
gyverencoder/GyverEncoder.cpp

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;
}
}