//
// StMPK.ino
// System Tablic MPK
//
// Created by Tobiasz Kropidłowski and Cyprian Zaradniak on 12.09.2024.
//
// Idea Cyprian
// Help by Miłosz
//
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
// YOU CAN EDIT THIS VALUES \/ \/ \/ \/ \/ \/ \/ \/ \/
String bootText[] = {"Wczytywanie...", "MPK Sp. z o.o."}; //boot system texts
int bootLoadingTime = 3; //startup duration (in seconds)
int positionsInIndex = 37; //enter how many positions you have in the "lines" index (count from 1)
int refresh = 2; //how often should the board be refreshed? 2 = 1 second
int lines[] = {12, 15, 14, 16, 12, 15, 14, 16, 12, 15, 14, 16, 12, 15, 14, 16, 12, 15, 14, 16, 12, 15, 14, 16, 12, 15, 14, 201, 14, 15, 3, 202, 12, 201, 202, 201, 202};
int departure[] = {3, 8, 14, 20, 23, 28, 34, 40, 43, 48, 54, 60, 63, 68, 74, 80, 83, 88, 94, 100, 103, 108, 114, 120, 123, 128, 134, 135, 143, 149, 150, 152, 153, 165, 182, 195, 212};
int isInvalid[] = {0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1,}; //0 is no, 1 is yes
int isChangeRoute[] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1}; //0 is no, 1 is yes
String direction[] = {"Star. PKM", "Budziszyn.", "Gorcz. PKM", "Franowo", "Star. PKM", "Budziszyn.", "Gorcz. PKM", "Franowo", "Star. PKM", "Budziszyn.", "Gorcz. PKM", "Franowo", "Star. PKM", "Budziszyn.", "Gorcz. PKM", "Franowo", "Star. PKM", "Budziszyn.", "Gorcz. PKM", "Franowo", "Star. PKM", "Budziszyn.", "Gorcz. PKM", "Franowo", "Star. PKM", "Budziszyn.", "Gorcz. PKM", "Unii Lub.", "Zaj. Glog.", "Zaj. Glog.", "Wlodarska", "Franowo", "Star. PKM", "Unii Lub.", "Franowo", "Unii Lub.", "Franowo"};
String shutdownText[] = {"~~~~~~~~~~~~~~~~~~~~", " BRAK KURSOW", " W DNIU DZISIEJSZYM", "~~~~~~~~~~~~~~~~~~~~", "Sending Raport...", "12.09.2024 22:21", "System shuting down"};
String blinkAnim[] = {"<1min", " ", "<1min", " "};
// ATTENTION !! Each array must have the same number of positions that
//you enter into int positionsInIndex, e.g. lines[] has 7 positions,
//so each array must also have 7, i.e. you enter 7 as the value of positionsInIndex
// /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
int lcdLine = 0;
int acc = 0;
int loops = 0;
int decreaseMin = 0;
int blink = 0;
int wait = 0;
byte inwalida[] = {0x0C, 0x0C, 0x08, 0x0E, 0x08, 0x0E, 0x11, 0x0E};
byte changeRoute[] = {0x1B, 0x11, 0x1B, 0x13, 0x17, 0x11, 0x1D, 0x1D};
void setup() {
//init screen + create char
lcd.begin(20, 4);
lcd.backlight();
lcd.createChar(0, inwalida); lcd.createChar(1, changeRoute);
//Logo boot loop
for(int i=0; i<bootLoadingTime; i++) {
lcd.setCursor(3, 0);
lcd.print(bootText[0]);
lcd.setCursor(3, 3);
lcd.print(bootText[1]);
delay(500);
lcd.clear();
delay(500);
}
}
void loop() {
while(lcdLine<4) {
//Display line
lcd.setCursor(0, lcdLine);
lcd.print(acc < positionsInIndex ? String(lines[acc]) : " ");
//Display direction
lcd.setCursor(3, lcdLine);
lcd.print(acc < positionsInIndex ? direction[acc] : " ");
//Set invalid icon
lcd.setCursor(14, lcdLine);
lcd.write((acc < positionsInIndex && isInvalid[acc]) ? 0 : ' ');
//Change route icon
lcd.setCursor(13, lcdLine);
lcd.write((acc < positionsInIndex && isChangeRoute[acc]) ? 1 : ' ');
//Display minutes
lcd.setCursor(15, lcdLine);
lcd.print(acc < positionsInIndex ? (departure[acc] < 1 ? blinkAnim[wait] : String(departure[acc]) + "min") : " ");
acc++;
lcdLine++;
if(lcdLine > 4){lcdLine = 0;}
}
delay(refresh * 125);
wait++;
//Decrease minutes from table
if(wait == 4){
while(decreaseMin<positionsInIndex) {
departure[decreaseMin] --;
decreaseMin++;
}
wait = 0;
}
decreaseMin = 0;
lcd.clear();
acc = 0 + loops;
if(departure[acc] > 0) {lcdLine = 0;}
else if(departure[acc] <= 0){
blink++;
lcdLine = 0;
if(blink == 4) {loops++; blink = 0;}
}
shutdown();
}
void shutdown() {
while(departure[positionsInIndex - 1] < -1) {
for(int i = 0; i<6; i++) {
lcd.setCursor(0, i < 4 ? i : i - 4);
if (i < 4 || i > 3) {
lcd.print(shutdownText[i]);
}
if (i == 3) {
sClear();
}
}
sClear();
lcd.print(shutdownText[6]);
sClear();
lcd.noBacklight();
departure[positionsInIndex - 1] = 1000;
}
}
void sClear() {
delay(2000);
lcd.setCursor(0, 0);
lcd.clear();
}