#include <Encoder.h>                        // https://www.pjrc.com/teensy/td_libs_Encoder.html
#include <Toggle.h>                         // https://github.com/Dlloydev/Toggle

class Codeur {
    Encoder encodeur;
    char plus, moins;
    long valeurPrecedente = 0;

  public:
    Codeur(const byte dtPin, const byte clkPin, const char p, const char m):
      encodeur(dtPin, clkPin), plus(p), moins(m) {}

    void begin() {
      encodeur.write(0);
    }

    void check() {
      long v = encodeur.read() >> 2; // on divise par 4 car l'encdeur envoie 4 ticks par clicks
      if (v != valeurPrecedente) {
        // la valeur a changé
        if (v > valeurPrecedente) {
          for (long i = 0; i < v - valeurPrecedente; i++) Serial.print(plus);
        } else {
          for (long i = 0; i < valeurPrecedente - v; i++) Serial.print(moins);
        }
        valeurPrecedente = v;
      }
    }
};

class Bouton {
  public:
    Toggle bouton;
    const byte pin;
    char down, up;

  public:
    Bouton(const byte p, const char d, const char u)  : bouton(p), pin(p), down(d), up(u) {};

    void begin() {
      bouton.begin(pin);
    }

    void check() {
      bouton.poll();
      if (bouton.onPress())   Serial.print(down);
      if (bouton.onRelease()) Serial.print(up);
    }
};

Codeur encodeurs[] = {{3, 2, 'a', 'z'}, {6, 5, 'e', 'r'}, {9, 8, 't', 'y'}};
Bouton boutons[] = {{4, 'q', 's'}, {7, 'd', 'f'}, {10, 'g', 'h'}, {11, 'j', 'k'}, {12, 'l', 'm'}, {13, 'w', 'x'}};

const byte sigPin = A0;
const byte selectPins[] = {A4, A3, A2, A1};
uint16_t oldMuxValue;

char muxKeys[][2] = {
  {'0', '1'},  // CH0 ('1' quand sélectionné, '0' quand relâché)
  {'2', '3'},
  {'4', '5'},
  {'6', '7'},
  {'8', '9'},
  {'A', 'B'},
  {'C', 'D'},
  {'E', 'F'},
  {'G', 'H'},
  {'I', 'J'},
  {'K', 'L'},
  {'M', 'N'},
  {'O', 'P'},
  {'Q', 'R'},
  {'S', 'T'},
  {'U', 'V'},   // CH15 ('V' quand sélectionné, 'U' quand relâché)
};



uint16_t readMux() {
  uint16_t result = 0;
  for (byte channel = 0; channel < 16; channel++) {
    for (int i = 4; i >= 0; --i) digitalWrite(selectPins[i], (bitRead(channel, i) == 1) ? HIGH : LOW);
    delay(10);
    if (analogRead(sigPin) > 500) bitSet(result, channel);
  }
  return result;
}




void setup() {
  for (byte p : selectPins)pinMode(p, OUTPUT);
  for (Codeur& c : encodeurs) c.begin();
  for (Bouton& b : boutons) b.begin();
  oldMuxValue = readMux();
  Serial.begin(115200);
  Serial.println(F("PRET!"));
}

void loop() {
  uint16_t muxValue = readMux();
  if (muxValue != oldMuxValue) {
    for (byte channel = 0; channel < 16; channel++) {
      if (bitRead(muxValue, channel) != bitRead(oldMuxValue, channel))
        Serial.write(muxKeys[channel][bitRead(muxValue, channel)]);
    }
    oldMuxValue = muxValue;
  }
  
  for (Codeur& c : encodeurs) c.check();
  for (Bouton& b : boutons) b.check();
}