/*Simple sketch to demonstrate using the TM1637 display and a rotation encoder
based on code from Ralph Bacon https://github.com/RalphBacon/226-Better-Rotary-Encoder---no-switch-bounce
and from Marko Pinteric (https://www.pinteric.com/mped.html
using the interrupt pins to avoid bounce
Note on the UNO this circuit requires both interrupt pins to be used
which leaves no other options for other hardware interrupts
*/

//add the display library
#include <TM1637Display.h>
//set up display
// Define the connections pins for display:
#define CLOCKA 7
#define DIOA 8
//power encoder, for test circuit
#define VROT1 12

// Create display object of type TM1637Display:
//so it turns out that adding an optional delay allows the display to work without affecting interrupts
TM1637Display displaya = TM1637Display(CLOCKA, DIOA, 11);
int bright=1;

//configure the rot encoder
#include <Arduino.h>

// Rotary encoder pins
//Note I had tried to use more than one
//Pins 2 and 3 are the only interrupt pins, it is therefore not possible to use more than one rotary encoder as it requires botgh interrupts
#define PIN_A 2
#define PIN_B 3
#define PUSH_BTN 4

// A turn counter for the rotary encoder (negative = anti-clockwise)
int rotationCounter = 0; //start count at zero

// Flag from interrupt routine (moved=true)
volatile bool rotaryEncoder = false;

// Interrupt routine just sets a flag when rotation is detected


void rotary()
{
    rotaryEncoder = true;
}


// Rotary encoder has moved (interrupt tells us) but what happened?
// See https://www.pinteric.com/rotary.html
int8_t checkRotaryEncoder()
{
    // Reset the flag that brought us here (from ISR)
      rotaryEncoder = false;

    static uint8_t lrmem = 3;
    static int lrsum = 0;
    static int8_t TRANS[] = {0, -1, 1, 14, 1, 0, 14, -1, -1, 14, 0, 1, 14, 1, -1, 0};

    // Read BOTH pin states to deterimine validity of rotation (ie not just switch bounce)
    int8_t l = digitalRead(PIN_A);
    int8_t r = digitalRead(PIN_B);

    // Move previous value 2 bits to the left and add in our new values
    lrmem = ((lrmem & 0x03) << 2) + 2 * l + r;

    // Convert the bit pattern to a movement indicator (14 = impossible, ie switch bounce)
    lrsum += TRANS[lrmem];

    /* encoder not in the neutral (detent) state */
    if (lrsum % 4 != 0)
    {
        return 0;
    }

    /* encoder in the neutral state - clockwise rotation*/
    if (lrsum == 4)
    {
        lrsum = 0;
        return 1;
    }

    /* encoder in the neutral state - anti-clockwise rotation*/
    if (lrsum == -4)
    {
        lrsum = 0;
        return -1;
    }

    // An impossible rotation has been detected - ignore the movement
    lrsum = 0;
    return 0;
}



void setup() {
  Serial.begin(115200);
  //for displaya
  pinMode(CLOCKA, OUTPUT);
  pinMode(DIOA, OUTPUT);
  //power pins for the rotary encoders
  //not this is just for the test rig, they will be connected to VCC in final
  pinMode(VROT1, OUTPUT);

  //turn on the encoder
  digitalWrite(VROT1, HIGH);
  displaya.setBrightness(bright);
  //display INFO
  displaya.showNumberDec(-1);

  // The module already has pullup resistors on board.
  pinMode(PIN_A, INPUT);
  pinMode(PIN_B, INPUT);
 
  // But not for the push switch
  pinMode(PUSH_BTN, INPUT_PULLUP);

  // We need to monitor both pins, rising and falling for all states
  attachInterrupt(digitalPinToInterrupt(PIN_A), rotary, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_B), rotary, CHANGE);
  
  
  Serial.println("Setup completed");
  displaya.showNumberDec(0);

}

//main routine
void loop()
{
  // Has rotary encoder moved?
  if (rotaryEncoder)
  {
      // Get the movement (if valid)
      int8_t rotationValue = checkRotaryEncoder();

      // If valid movement, do something
      if (rotationValue != 0)
      {
          rotationCounter += rotationValue * 1;
          Serial.print(rotationValue < 1 ? "L:" :  "R:");
          Serial.println(rotationCounter);
          if(rotationCounter<=7 & rotationCounter>=0){

              //Set the brightness of the display 0 to 7
              displaya.setBrightness(rotationCounter);
          }
          displaya.showNumberDec(rotationCounter);
        }
  }

  if (digitalRead(PUSH_BTN) == LOW)
  {
      rotationCounter = 0;
      Serial.print("B:");
      Serial.println(rotationCounter);
      displaya.showNumberDec(rotationCounter);
      
      //don't repeat for 500 miliseconds
      delay(500);

  }
  


}


4-Digit Display