#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <LiquidCrystal_I2C.h>
// Define the number of displays and data pin configurations for MAX72XX
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 16 // 4x4 matrix configuration
#define DATA_PIN 11
#define CLK_PIN 13
#define CS_PIN 10
// Define matrix configuration
#define MATRIX_ROWS 4
#define MATRIX_COLS 4
// Initialize the Parola display object
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MATRIX_ROWS * MATRIX_COLS);
LiquidCrystal_I2C lcd(0x27, 20, 4); // Set the LCD I2C address
char lineBuff[5][33]; // Buffer for 5 lines of text, each up to 32 characters
int lineA;
int lineB;
int lineC;
int mulai;
int seconds;
int cs;
long start_time = 0;
int lapa = 0, lapb = 0, lapc = 0;
bool btlastlap = false; // Boolean for lastlap toggle
void setup(void)
{
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
pinMode(5, INPUT_PULLUP); // Push button for toggling lastlap
Serial.begin(9600);
// Initialize Parola display
P.begin();
P.setIntensity(5); // Set brightness level (0-15)
P.displayClear();
lcd.init();
lcd.backlight();
lcd.clear();
}
void loop(void)
{
if (P.displayAnimate()) {
P.displayReset();
}
// Read input pins
lineA = digitalRead(2);
lineB = digitalRead(3);
lineC = digitalRead(4);
// Toggle btlastlap using the push button
if (digitalRead(5) == LOW) {
delay(200); // Debouncing delay
btlastlap = !btlastlap; // Toggle the boolean
while (digitalRead(5) == LOW); // Wait for button release
}
if (btlastlap) { // If lastlap is active
if (checkLines(lineA, lineB, lineC)) {
delay(1);
}
displayResults();
} else { // If lastlap is inactive
if (checkLines(lineA, lineB, lineC)) {
P.displayClear();
displayScrollingText("WIN", PA_CENTER, 100, 2000);
processResults(lineA, lineB, lineC);
}
}
if (checkStartCondition(lineA, lineB, lineC)) {
mulai = 1;
start_time = millis();
displayScrollingText("ENGINE ON", PA_CENTER, 100, 2000);
}
if (mulai == 1) {
seconds = (millis() - start_time) / 1000;
cs = ((millis() - start_time) / 10) % 100;
}
displayTimeAndLap();
}
bool checkLines(int a, int b, int c) {
return ((a == 0 && b == 1 && c == 1) ||
(a == 1 && b == 0 && c == 1) ||
(a == 1 && b == 1 && c == 0) ||
(a == 0 && b == 0 && c == 1) ||
(a == 0 && b == 1 && c == 0) ||
(a == 1 && b == 0 && c == 0) ||
(a == 0 && b == 0 && c == 0)) && (mulai == 1);
}
bool checkStartCondition(int a, int b, int c) {
return (a == 0 || b == 0 || c == 0) && mulai == 0;
}
void displayResults() {
if (lapa) {
displayScrollingText("WIN A", PA_CENTER, 100, 2000);
hasila();
} else if (lapb) {
displayScrollingText("WIN B", PA_CENTER, 100, 2000);
hasilb();
} else if (lapc) {
displayScrollingText("WIN C", PA_CENTER, 100, 2000);
hasilc();
}
}
void processResults(int a, int b, int c) {
if (a == 0 && b == 1 && c == 1) {
hasila();
} else if (a == 1 && b == 0 && c == 1) {
hasilb();
} else if (a == 1 && b == 1 && c == 0) {
hasilc();
}
}
void displayTimeAndLap() {
sprintf(lineBuff[0], "%02d:%02d", seconds, cs);
sprintf(lineBuff[1], "A:%02d:%02d", lapa / 60, lapa % 60);
sprintf(lineBuff[2], "B:%02d:%02d", lapb / 60, lapb % 60);
sprintf(lineBuff[3], "C:%02d:%02d", lapc / 60, lapc % 60);
P.setTextAlignment(PA_LEFT);
P.setTextEffect(0, PA_PRINT, PA_NO_EFFECT);
for (int i = 0; i < 4; i++) {
P.displayText(lineBuff[i], PA_LEFT, 0, 0, PA_PRINT, PA_NO_EFFECT);
P.displayAnimate();
P.setFont(NULL); // Reset to default font
P.setTextEffect(0, PA_PRINT, PA_NO_EFFECT);
}
// LCD display
lcd.clear();
for (int i = 0; i < 4; i++) {
lcd.setCursor(0, i);
lcd.print(lineBuff[i]);
}
}
void displayScrollingText(const char* msg, textPosition_t alignment, uint16_t speed, uint16_t pause) {
P.displayText(msg, alignment, speed, pause, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
while (!P.displayAnimate());
}
void hasila() {
displayScrollingText("A", PA_CENTER, 100, 2000);
}
void hasilb() {
displayScrollingText("B", PA_CENTER, 100, 2000);
}
void hasilc() {
displayScrollingText("C", PA_CENTER, 100, 2000);
}