#include "esp_log.h"
#define LOG_TAG "yoEncoder"
#include "yoEncoder.h"
void IRAM_ATTR yoEncoder::readEncoder_ISR()
{
unsigned long now = millis();
portENTER_CRITICAL_ISR(&(this->mux));
if (this->isEnabled)
{
this->old_AB <<= 2;
int8_t ENC_PORT = ((digitalRead(this->encoderBPin)) ? (1 << 1) : 0) | ((digitalRead(this->encoderAPin)) ? (1 << 0) : 0);
this->old_AB |= (ENC_PORT & 0x03);
int8_t currentDirection = (this->enc_states[(this->old_AB & 0x0f)]);
if (currentDirection != 0)
{
long prevRotaryPosition = this->encoder0Pos / this->encoderSteps;
this->encoder0Pos += currentDirection;
long newRotaryPosition = this->encoder0Pos / this->encoderSteps;
if (newRotaryPosition != prevRotaryPosition && rotaryAccelerationCoef > 1)
{
unsigned long accelerationLongCutoffMillis = 200;
unsigned long accelerationShortCutffMillis = 4;
if (currentDirection == lastMovementDirection &&
currentDirection != 0 &&
lastMovementDirection != 0)
{
unsigned long millisAfterLastMotion = now - lastMovementAt;
if (millisAfterLastMotion < accelerationLongCutoffMillis)
{
if (millisAfterLastMotion < accelerationShortCutffMillis)
{
millisAfterLastMotion = accelerationShortCutffMillis;
}
if (currentDirection > 0)
{
this->encoder0Pos += rotaryAccelerationCoef / millisAfterLastMotion;
}
else
{
this->encoder0Pos -= rotaryAccelerationCoef / millisAfterLastMotion;
}
}
}
this->lastMovementAt = now;
this->lastMovementDirection = currentDirection;
}
if (this->encoder0Pos > (this->_maxEncoderValue))
this->encoder0Pos = this->_circleValues ? this->_minEncoderValue : this->_maxEncoderValue;
if (this->encoder0Pos < (this->_minEncoderValue))
this->encoder0Pos = this->_circleValues ? this->_maxEncoderValue : this->_minEncoderValue;
}
}
portEXIT_CRITICAL_ISR(&(this->mux));
}
yoEncoder::yoEncoder(uint8_t encoder_APin, uint8_t encoder_BPin, uint8_t encoderSteps, bool internalPullup)
{
this->old_AB = 0;
this->encoderAPin = encoder_APin;
this->encoderBPin = encoder_BPin;
this->encoderSteps = encoderSteps;
pinMode(this->encoderAPin, internalPullup?INPUT_PULLUP:INPUT);
pinMode(this->encoderBPin, internalPullup?INPUT_PULLUP:INPUT);
}
void yoEncoder::setBoundaries(long minEncoderValue, long maxEncoderValue, bool circleValues)
{
this->_minEncoderValue = minEncoderValue * this->encoderSteps;
this->_maxEncoderValue = maxEncoderValue * this->encoderSteps;
this->_circleValues = circleValues;
}
long yoEncoder::readEncoder()
{
return (this->encoder0Pos / this->encoderSteps);
}
void yoEncoder::setEncoderValue(long newValue)
{
reset(newValue);
}
long yoEncoder::encoderChanged()
{
long _encoder0Pos = readEncoder();
long encoder0Diff = _encoder0Pos - this->lastReadEncoder0Pos;
this->lastReadEncoder0Pos = _encoder0Pos;
return encoder0Diff;
}
void yoEncoder::setup(void (*ISR_callback)(void))
{
attachInterrupt(digitalPinToInterrupt(this->encoderAPin), ISR_callback, CHANGE);
attachInterrupt(digitalPinToInterrupt(this->encoderBPin), ISR_callback, CHANGE);
}
void yoEncoder::begin()
{
this->lastReadEncoder0Pos = 0;
}
void yoEncoder::reset(long newValue_)
{
newValue_ = newValue_ * this->encoderSteps;
this->encoder0Pos = newValue_;
this->lastReadEncoder0Pos = this->encoder0Pos;
if (this->encoder0Pos > this->_maxEncoderValue)
this->encoder0Pos = this->_circleValues ? this->_minEncoderValue : this->_maxEncoderValue;
if (this->encoder0Pos < this->_minEncoderValue)
this->encoder0Pos = this->_circleValues ? this->_maxEncoderValue : this->_minEncoderValue;
}
void yoEncoder::enable()
{
this->isEnabled = true;
}
void yoEncoder::disable()
{
this->isEnabled = false;
}