#include <Keypad.h>
#include <TM1637Display.h>
#define CLK1 22
#define DIO1 23
#define CLK2 21
#define DIO2 19
#define ROTARY_PIN1 26
#define ROTARY_PIN2 27
#define ROTARY_BUTTON 25
#define DEBOUNCE_DELAY 200
#define RESET_DEBOUNCE_DELAY 100
TM1637Display display1(CLK1, DIO1);
TM1637Display display2(CLK2, DIO2);
const byte ROWS = 4;
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {16, 17, 18, 0};
byte colPins[COLS] = {2, 4, 5, 15};
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
int lastEncoded = 0;
unsigned long lastDebounceTime = 0;
int availableScores[] = {101, 180, 301, 501, 701, 901};
int playerScores[2] = {0, 0};
int scoreIndex = 3;
bool scoreLocked = false;
int currentPlayer = 1;
String currentInput = "";
int previousScores[3] = {0, 0, 0}; // Array per memorizzare gli ultimi tre punteggi
int previousPlayers[3] = {0, 0, 0}; // Array per memorizzare i giocatori associati ai punteggi
int scoreIndexHistory = 0; // Indice per tenere traccia della posizione corrente nell'array
int lastPlayer = 0;
void handleRotaryEncoder() {
if (scoreLocked) return;
int MSB = digitalRead(ROTARY_PIN1);
int LSB = digitalRead(ROTARY_PIN2);
int currentEncoded = (MSB << 1) | LSB;
int sum = (lastEncoded << 2) | currentEncoded;
unsigned long currentTime = millis();
if (currentTime - lastDebounceTime > DEBOUNCE_DELAY) {
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
scoreIndex = min(scoreIndex + 1, (int)(sizeof(availableScores) / sizeof(availableScores[0]) - 1));
display1.showNumberDec(availableScores[scoreIndex], false);
lastDebounceTime = currentTime;
} else if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
scoreIndex = max(scoreIndex - 1, 0);
display1.showNumberDec(availableScores[scoreIndex], false);
lastDebounceTime = currentTime;
}
}
lastEncoded = currentEncoded;
}
void handleButtonPress() {
bool buttonState = digitalRead(ROTARY_BUTTON) == LOW;
if (buttonState && !scoreLocked && millis() - lastDebounceTime > DEBOUNCE_DELAY) {
scoreLocked = true;
playerScores[0] = availableScores[scoreIndex];
playerScores[1] = availableScores[scoreIndex];
currentPlayer = 1;
updateDisplays();
lastDebounceTime = millis();
}
}
void handleKeypad() {
if (!scoreLocked) return;
char key = customKeypad.getKey();
if (key) {
if (key == 'A') {
scoreIndex = 3;
scoreLocked = false;
display1.showNumberDec(availableScores[scoreIndex], false);
display2.clear();
} else if (key == 'B') {
for (int i = 0; i < 3; i++) {
if (previousPlayers[i] != 0) {
playerScores[previousPlayers[i] - 1] += previousScores[i];
}
}
updateDisplays();
} else if (key == '#') {
if (currentInput.length() > 0) {
int score = currentInput.toInt();
previousScores[scoreIndexHistory % 3] = score; // Memorizza il punteggio nell'array
previousPlayers[scoreIndexHistory % 3] = currentPlayer; // Memorizza il giocatore nell'array
scoreIndexHistory++;
playerScores[currentPlayer - 1] -= score;
currentInput = "";
currentPlayer = currentPlayer % 2 + 1;
updateDisplays();
}
} else if (isdigit(key)) {
currentInput += key;
displayCurrentInput();
}
}
}
uint8_t* getDigitSegments(int num) {
static uint8_t segData[4];
for (int i = 0; i < 4; i++) {
segData[i] = 0;
}
int digitPos = 3;
do {
segData[digitPos--] = display1.encodeDigit(num % 10);
num /= 10;
} while (num > 0 && digitPos >= 0);
return segData;
}
void updateDisplays() {
uint8_t segPlayer1[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t segPlayer2[4] = {0x00, 0x00, 0x00, 0x00};
memcpy(segPlayer1, getDigitSegments(playerScores[0]), 4);
memcpy(segPlayer2, getDigitSegments(playerScores[1]), 4);
if (currentPlayer == 1) {
segPlayer1[0] |= 0x40;
} else {
segPlayer2[0] |= 0x40;
}
display1.setSegments(segPlayer1);
display2.setSegments(segPlayer2);
}
void displayCurrentInput() {
uint8_t segData[4] = {0x00, 0x00, 0x00, 0x00};
memcpy(segData, getDigitSegments(currentInput.toInt()), 4);
if (currentPlayer == 1) {
display1.setSegments(segData);
} else {
display2.setSegments(segData);
}
}
void setup() {
Serial.begin(9600);
pinMode(ROTARY_PIN1, INPUT_PULLUP);
pinMode(ROTARY_PIN2, INPUT_PULLUP);
pinMode(ROTARY_BUTTON, INPUT_PULLUP);
display1.setBrightness(0x0f);
display2.setBrightness(0x0f);
display1.showNumberDec(availableScores[scoreIndex], false);
display2.clear();
}
void loop() {
if (!scoreLocked) {
handleRotaryEncoder();
}
handleButtonPress();
handleKeypad();
}