Skip to content
Snippets Groups Projects
RotaryEncoder.hpp 1.82 KiB
Newer Older
#ifndef ROTARYENCODER_h
#define ROTARYENCODER_h

class RotaryEncoder {

    // Private members:

    int _pinA;
    int _pinB;
    volatile int _state[2];
    volatile int _position;
    volatile bool _inputFlag = false;
    bool _changeFlag = false;

    unsigned long _previousTimer;
    int _interval = 200;

    void (*_cb)(RotaryEncoder*, uint8_t, int); // Callback function

    // {newPin2, newPin1, oldPin2, oldPin1}
    int movements[5][4][4] = {
      { // No movement
        {0, 0, 0, 0},
        {0, 1, 0, 1},
        {1, 0, 1, 0},
        {1, 1, 1, 1}
      },
      { // +1
        {0, 0, 0, 1},
        {0, 1, 1, 1},
        {1, 0, 0, 0},
        {1, 1, 1, 0}
      },
      { // -1
        {0, 0, 1, 0},
        {0, 1, 0, 0},
        {1, 0, 1, 1},
        {1, 1, 0, 1}
      },
      { // +2
        {0, 0, 1, 1},
        {1, 1, 0, 0}
      },
      { // -2
        {0, 1, 1, 0},
        {1, 0, 0, 1}
      },
    };

    // Private Functions:

    void _setState(int a, int b);
    void _incrementPosition(int delta);
    int _findChange(int state1[2], volatile int state2[2]);
    boolean _compareArrays(int a[4], int b[4]);
    // Public members:

    static const uint8_t kEventStableUpdate = 0;
    static const uint8_t kEventUnstableUpdate = 1;

    //Public Functions:

    RotaryEncoder(int pinA, int pinB, int id = 99) : _pinA(pinA), _pinB(pinB), _id(id) {
      pinMode(_pinA, INPUT_PULLUP);
      pinMode(_pinB, INPUT_PULLUP);

      _previousTimer = millis();
      _setState(digitalRead(_pinA), digitalRead(_pinB));
      setPosition(0);
    }

    void initInterrupts(void(*function)());
    void setEventHandler(void(*function)(RotaryEncoder*, uint8_t, int));
    int getPostition();
    int getId();
    void setPosition(int value);
    void check();
    void ICACHE_RAM_ATTR tick();