Line data Source code
1 : #pragma once 2 : 3 : #include <AH/STL/type_traits> 4 : #include <Settings/NamespaceSettings.hpp> 5 : #include <stdint.h> 6 : 7 : BEGIN_CS_NAMESPACE 8 : 9 : /// Class to keep track of relative position changes of rotary encoders. 10 : template <class Enc_t> 11 : class EncoderState { 12 : private: 13 : using SignedEnc_t = typename std::make_signed<Enc_t>::type; 14 : int16_t speedMultiply; 15 : uint8_t pulsesPerStep; 16 : int16_t remainder = 0; 17 : Enc_t deltaOffset = 0; 18 : 19 : public: 20 21 : EncoderState(int16_t speedMultiply, uint8_t pulsesPerStep) 21 21 : : speedMultiply(speedMultiply), pulsesPerStep(pulsesPerStep) {} 22 : 23 35 : int16_t update(Enc_t encval) { 24 : // If Enc_t is an unsigned type, integer overflow is well-defined, which 25 : // is what we want when Enc_t is small and expected to overflow. 26 : // However, we need it to be signed because we're interested in the 27 : // delta. 28 35 : Enc_t uDelta = encval - deltaOffset; 29 35 : if (uDelta == 0) 30 2 : return 0; 31 33 : int16_t delta = static_cast<SignedEnc_t>(uDelta); 32 : // Assumption: delta and speedMultiply are relatively small, so 33 : // multiplication probably won't overflow. 34 33 : int16_t multipliedDelta = delta * speedMultiply + remainder; 35 33 : int16_t scaledDelta = multipliedDelta / pulsesPerStep; 36 33 : remainder = multipliedDelta % pulsesPerStep; 37 33 : deltaOffset += uDelta; 38 33 : return scaledDelta; 39 : } 40 : void setSpeedMultiply(int16_t speedMultiply) { 41 : // TODO: Is this correct? Is it necessary? What with negative speedMult? 42 : remainder = remainder * speedMultiply / this->speedMultiply; 43 : this->speedMultiply = speedMultiply; 44 : } 45 : int16_t getSpeedMultiply() const { return this->speedMultiply; } 46 : }; 47 : 48 : END_CS_NAMESPACE