#include <MD_MAX72xx.h>    // https://github.com/MajicDesigns/MD_MAX72XX
#include <MD_Parola.h>     // https://github.com/MajicDesigns/MD_Parola
#include <Button_SL.hpp>   // https://github.com/DoImant/Button_SL
#include <SPI.h>

using namespace Btn;

constexpr uint8_t NUM_COUNTER {4};

constexpr uint8_t MAX_DEVICES {5};
constexpr uint8_t CLK_PIN {13};
constexpr uint8_t DATA_PIN {11};
constexpr uint8_t CS_PIN {10};

// KLasse zum speichern und addieren der Punktzahl, mit der sie initialisiert wird
class ScoreCounter {
public:
  ScoreCounter(uint16_t points, uint32_t sum = 0) : points {points}, sum {sum} {}
  uint16_t operator()() {   // Addiere pro Kontakt die initialisierte Punktzahl
    sum += points;
    return points;          // Gib initialisierte Punktzahl zurück. Z.b. für eine andere Addition
  }
  uint32_t getSum() const { return sum; }   // Gebe Summe für die Kontakte * initialisierte Punktzahl zurück

private:
  const uint16_t points;
  uint32_t sum;
};

//
// Abfrage der Kontaktpins. Diese sind Active-Low konfiguriert (INPUT_PULLUP)
// Kann über die Buttonklasse aber auch auf Active High umkonfigurierte werden.
// Rückgabewert ist der Index des Kontaktpins im Array. (-1) = kein Kontakt festgestellt.
//
template <size_t N> int checkSignals(ButtonSL (&btn)[N]) {
  for (size_t i = 0; i < N; ++i) {
    if (btn[i].tick() != ButtonState::notPressed) {
      return i;
    }
  }
  return -1;
}

// Array für die Pinabfrage anlegen. Das Lesen der Pins erfolgt entprellt
// Standard Entprellzeit ist 30ms
ButtonSL signals[NUM_COUNTER] {{4,1000,HIGH}, {5,1000,HIGH}, {6,1000,HIGH}, {7,1000,HIGH}};

// Für jede gewünschte Punktzahl (pro Kontakt) ein Objekt anlegen
// Der Array-Reihenfolge (Index) muss mit dem Button Array identisch sein
ScoreCounter score[NUM_COUNTER] {10, 100, 1000, 10000};

// Display
MD_Parola mx = MD_Parola(MD_MAX72XX::PAROLA_HW, CS_PIN, MAX_DEVICES);

void setup() {
  Serial.begin(115200);
  // Initialisieren der Buttonobjekte
  for (auto& signal : signals) {
    signal.begin();
  }   

  mx.begin();
  mx.displayText("", PA_RIGHT, 0, 0, PA_PRINT, PA_NO_EFFECT);
  mx.print(0);
}

void loop() {
  static uint32_t scoreSum {0};   // Speicher für die Punktzahlsumme

  int8_t index = checkSignals(signals);   // Abfrage der Kontaktpins
  if (index > (-1)) {                     // Wenn ein Kontakt festgestellt wird die jeweilige Punktzahl addieren
    scoreSum += score[index]();
    mx.print(scoreSum);                   // Kein Test auf Überlauf Stellenzahl!
    Serial.print("Score: ");
    Serial.println(scoreSum);
  }
}
10er
100er
1000er
10000er