tt.h
void bigDisplay();
/*
0 | 7 |
5 1 | 2 6 |
6 | 1 |
4 2 | 3 5 |
3 | 4 |
*/
/*
Digit0 Timer Hunderter // Minute Einer
Digit1 Timer zehner // Sekunde Zehner
Digit2 Timer einer // Sekunde Einer
Digit3 SpielerA Satz + Aufschlag D40
Digit4 SpielerA Punkte einer + Zehner D32
Digit5 SpielerB Satz + Aufschlag D24
Digit6 SpielerB Punkte einer + Zehner D16
*/
constexpr bool segActiv {0}; // Die Segmente leuchten, wenn RegisterPin => 0!!!
constexpr uint8_t bigDisp {1}; // -> Nummer des Registerzweig aus displays
constexpr uint8_t bigDispReg {7}; // -> Anzahl der Register auf dem Zweig
bool bigDispRegOut[bigDispReg * 8] = {!segActiv}; // -> Summe aller bits auf dem Zweig
bool oldBigDisplay[bigDispReg * 8] = {!segActiv}; // Merker für Aktuallisierung
constexpr byte displays {3};
struct REGPIN
{
uint8_t clock;
uint8_t data;
uint8_t latch;
};
REGPIN regpin[displays]
{{5, 7, 6}, {9, 11, 10}, {12, 14, 13}};
boolean dec[][8] =
{
{1, 1, 0, 0, 0, 0, 0, 0}, // 0
{1, 1, 1, 1, 1, 0, 0, 1}, // 1
{1, 0, 1, 0, 0, 1, 0, 0}, // 2
{1, 0, 1, 1, 0, 0, 0, 0}, // 3
{1, 0, 0, 1, 1, 0, 0, 1}, // 4
{1, 0, 0, 1, 0, 0, 1, 0}, // 5
{1, 0, 0, 0, 0, 0, 1, 0}, // 6
{1, 1, 1, 1, 1, 0, 0, 0}, // 7
{1, 0, 0, 0, 0, 0, 0, 0}, // 8
{1, 0, 0, 1, 0, 0, 0, 0}, // 9
{1, 1, 1, 1, 1, 1, 1, 1}, // ALL OFF
};
constexpr uint8_t spielers {2};
struct SPIELER
{
uint8_t points;
uint8_t sets;
bool aufschlag;
};
SPIELER spieler[spielers]
{{0, 0, 0}, {0, 0, 0}};
REGPIN keypad
{16, 17, 15};
struct SCOREPAD
{
bool aufschlag; // 21 # 22
bool spielPlus; // 6 # 14
bool spielMinus; // 5 # 13
bool spielReset; // 4 # 12
bool satzPlus; // 3 # 11
bool satzMinus; // 2 # 10
bool satzReset; // 1 # 9
};
struct KEYTABLE
{
bool timeOutStart; // 20 Auszeit
bool timeOutStop; // 19
bool timeEinStart; // 18 Einspielzeit
bool timeEinStop; // 17
SCOREPAD sp[spielers]; // Spielertasten
};
constexpr bool gedrueckt {HIGH};
KEYTABLE kt;
KEYTABLE oldtable; // Hilfstabelle - hauptsächlich für das merken der Tastendrücke / kommt noch weg
struct ZEIT
{
/*
1+2 Minutenanzeige ( Anzeige 1 oder 2)( aber nur 2, 1 ist nicht in benutzung)
3 Sekundenanzeige zehner ( Anzeige 0-5)
4 Sekundenanzeige einer ( Anzeige 0-9)
*/
uint8_t minute = 0;
uint8_t sekunde = 0;
uint32_t lastTik = 0; // Merker, wann ausgelöst
} zeit;
//
void getKeys() // Funktion aus dem Ursprungspost übernommen und erweitert
{
// Das sind Schieberegister n:1
// Auch wenn nicht alle Pins gebraucht werden, müssen ungenutzte mitgelesen werden!
constexpr uint8_t zaehler {24}; // Anzahl Chips * 8 Pin
constexpr uint32_t interval {50}; // "debounce Time"
static uint32_t lastRead = 0; // Merker
if (millis() - lastRead > interval)
{
digitalWrite(keypad.latch, LOW); // Chip aktivieren
delay(1);
digitalWrite(keypad.latch, HIGH);
bool readIn = true;
for (uint8_t b = 0; b < zaehler; b++) // Eingänge durchzählen
{
readIn = digitalRead(keypad.data);
switch (b) // Zuweisung Pin => Variable
{
//*INDENT-OFF*
case 1: kt.sp[0].satzReset = readIn; break; // bit 1 aus Schieberegister
case 2: kt.sp[0].satzMinus = readIn; break; // bit 2
case 3: kt.sp[0].satzPlus = readIn; break; // bit 3
case 4: kt.sp[0].spielReset = readIn; break;
case 5: kt.sp[0].spielMinus = readIn; break;
case 6: kt.sp[0].spielPlus = readIn; break;
case 9: kt.sp[1].satzReset = readIn; break;
case 10: kt.sp[1].satzMinus = readIn; break;
case 11: kt.sp[1].satzPlus = readIn; break;
case 12: kt.sp[1].spielReset = readIn; break;
case 13: kt.sp[1].spielMinus = readIn; break;
case 14: kt.sp[1].spielPlus = readIn; break;
case 17: kt.timeEinStop = readIn; break;
case 18: kt.timeEinStart = readIn; break;
case 19: kt.timeOutStop = readIn; break;
case 20: kt.timeOutStart = readIn; break;
case 21: kt.sp[0].aufschlag = readIn; break;
case 22: kt.sp[1].aufschlag = readIn; break;
//*INDENT-ON*
}
digitalWrite(keypad.clock, HIGH);
digitalWrite(keypad.clock, LOW);
}
lastRead = millis();
}
}
//
void printSegment(const byte &segmentReihe, const bool *array, const byte &laenge)
{
for (uint8_t b = 0; b < laenge; b++)
{
digitalWrite(regpin[segmentReihe].data, array[b]); // Array auf dem Schieberegister
digitalWrite(regpin[segmentReihe].clock, HIGH);
digitalWrite(regpin[segmentReihe].clock, LOW);
digitalWrite(regpin[segmentReihe].data, LOW);
}
digitalWrite(regpin[segmentReihe].latch, HIGH);
digitalWrite(regpin[segmentReihe].latch, LOW);
}
//
void displayTime()
{
constexpr byte laenge {32};
bool time[laenge] = {0};
bool *timeSekundeEiner = &time[0];
bool *timeSekundeZehner = &time[8]; // 2.tes Register
bool *timeMinuteEiner = &time[16]; // 3.tes Register
bool *timeMinuteZehner = &time[24]; // 4.tes Register
memset(time, 0, laenge);
memcpy(timeMinuteZehner, dec[zeit.minute / 10], 8);
memcpy(timeMinuteEiner, dec[zeit.minute % 10], 8);
memcpy(timeSekundeZehner, dec[zeit.sekunde / 10], 8);
memcpy(timeSekundeEiner, dec[zeit.sekunde % 10], 8);
printSegment(2, time, laenge); // 3.ter Kanal
}
//
void displaySpieler()
{
/*
1+2 Punktanzeige Spieler A (Anzeige 0-19)
3+4 Satzanzeige Spieler A (Anzeige 0-9)( aber nur 3, 4 ist nicht in benutzung)
5+6 Satzanzeige Spieler B (Anzeige 0-9)( aber nur 5, 6 ist nicht in benutzung)
7+8 Punktanzeige Spieler B ( Anzeige 0-19)
*/
constexpr byte laenge {64};
bool spell[laenge] = {0};
bool *spielerBzehner = &spell[8];
bool *spielerBeiner = &spell[0];
bool *satzBeiner = &spell[24];
bool *satzAeiner = &spell[40];
bool *spielerAzehner = &spell[56];
bool *spielerAeiner = &spell[48];
memset(spell, 0, laenge);
memcpy(spielerAzehner, dec[spieler[0].points / 10], 8);
memcpy(spielerAeiner, dec[spieler[0].points % 10], 8);
memcpy(satzAeiner, dec[spieler[0].sets % 10], 8);
memcpy(satzBeiner, dec[spieler[1].sets % 10], 8);
memcpy(spielerBzehner, dec[spieler[1].points / 10], 8);
memcpy(spielerBeiner, dec[spieler[1].points % 10], 8);
printSegment(0, spell, laenge);
}
//
void bigDisplay()
{
constexpr uint32_t printIntervall {500};
static uint32_t lastPrint = 0;
memset(bigDispRegOut, !segActiv, bigDispReg * 8); // alle bits löschen
bool *timerHunderter = &bigDispRegOut[0 * 8]; // Register 7 | DIGIT 0
bool *timerZehner = &bigDispRegOut[1 * 8]; // Register 6 | DIGIT 1
bool *timerEiner = &bigDispRegOut[2 * 8]; // Register 5 | DIGIT 2
bool *spielerAsatz = &bigDispRegOut[3 * 8];
bool *spielerAeiner = &bigDispRegOut[4 * 8];
bool *spielerBsatz = &bigDispRegOut[5 * 8];
bool *spielerBeiner = &bigDispRegOut[6 * 8];
//
memcpy(timerHunderter, dec[zeit.minute % 10], 8);
memcpy(timerZehner, dec[zeit.sekunde / 10], 8);
memcpy(timerEiner, dec[zeit.sekunde % 10], 8);
memcpy(spielerAeiner, dec[spieler[0].points % 10], 8);
memcpy(spielerAsatz, dec[spieler[0].sets % 10], 8);
memcpy(spielerBeiner, dec[spieler[1].points % 10], 8);
memcpy(spielerBsatz, dec[spieler[1].sets % 10], 8);
bigDispRegOut[16] = spieler[1].points / 10 ? segActiv : !segActiv; // spielerBZehner
bigDispRegOut[24] = spieler[1].aufschlag ? segActiv : !segActiv; // spielerBAufschlag
bigDispRegOut[32] = spieler[0].points / 10 ? segActiv : !segActiv; // spielerAZehner
bigDispRegOut[40] = spieler[0].aufschlag ? segActiv : !segActiv; // spielerAAufschlag
for (byte b = 0; b < 56; b++)
{ bigDispRegOut[b] = !bigDispRegOut[b]; }
if ((memcmp(bigDispRegOut, oldBigDisplay, bigDispReg * 8) != 0) || // Neuer Inhalt ODER
(millis() - printIntervall > lastPrint)) // Zeit abgelaufen
{
for (byte b = 0; b < 56; b++)
{
Serial.print(bigDispRegOut[b]);
if ((b + 1) % 8 == 0)
{ Serial.print(" | "); }
}
Serial.println();
printSegment(bigDisp, bigDispRegOut, bigDispReg * 8);
memcpy(oldBigDisplay, bigDispRegOut, bigDispReg * 8);
lastPrint = millis();
}
//while (1);
};
void myTimer()
{
constexpr uint32_t _oneSecond {1000};
if (zeit.minute || zeit.sekunde) // Solange Zeit aktiv
{
if (millis() - zeit.lastTik >= _oneSecond)
{
if (zeit.sekunde > 0)
{ zeit.sekunde--; }
else if (zeit.minute > 0)
{
zeit.minute--;
zeit.sekunde = 59;
}
zeit.lastTik += _oneSecond;
}
}
}
//
void segmentTest()
{
for (byte b = 0; b < 10; b++)
{
for (byte s = 0; s < spielers; s++)
{
spieler[s].points = spieler[s].points ? 0 : 88;
spieler[s].sets = spieler[s].sets ? 0 : 88;
spieler[s].aufschlag = spieler[s].aufschlag ? 0 : 1;
}
zeit.minute = zeit.minute ? 0 : 88;
zeit.sekunde = zeit.sekunde ? 0 : 88;
displaySpieler();
displayTime();
bigDisplay();
delay(500);
}
}
//
void allNew()
{
for (byte s = 0; s < spielers; s++)
{
spieler[s].points = 0;
spieler[s].sets = 0;
spieler[s].aufschlag = false;
}
zeit.minute = 0;
zeit.sekunde = 0;
}
neuer Code:
#include "tt.h"
void setup()
{
Serial.begin(115200);
Serial.println(F("Tischtennis Display"));
//display init
for (byte b = 0; b < displays; b++)
{
pinMode(regpin[b].clock, OUTPUT);
pinMode(regpin[b].data, OUTPUT);
pinMode(regpin[b].latch, OUTPUT);
digitalWrite(regpin[b].clock, LOW);
digitalWrite(regpin[b].data, LOW);
digitalWrite(regpin[b].latch, LOW);
};
pinMode(keypad.clock, OUTPUT);
pinMode(keypad.data, INPUT);
pinMode(keypad.latch, OUTPUT);
digitalWrite(keypad.clock, LOW);
digitalWrite(keypad.latch, LOW);
segmentTest();
}
void loop()
{
getKeys(); // Holt Tastenzustände
checkKeys(); // wertet Tasten aus
myTimer(); // CountDownTimer
displaySpieler(); // kleine Anzeige
bigDisplay(); // große Anzeige
displayTime(); // countDownDisplay
}
/*
Angabe
Wird bei Start vergeben und danach alle 2 Punkte gewechselt....
Jetzt die Besonderheiten....
Ab Punktestand 10:10 wird nach jedem Punkt gewechselt
Im 5ten Satz werden die Seiten gewechselt wenn jemmand 5 Punkte erreicht hat das heißt
Angabe wechselt natürlich mit wie die Sätze und die Punkte auch
Nach beendeten Satz wird die Angabe gewechselt(Reset Punkte), d.h. SpielerA hat Angabe gewonnen, im 2ten Satz fängt SpielerB mit Angabe an, im dritten wieder SpielerA usw
So
Ist da was von Realisierbar?
*/
void nextAufschlag()
{
byte myAufschlag = 0;
for (byte b = 0; b < spielers; b++) // gehe durch alle Spieler
{
if (spieler[b].aufschlag) // Spieler hat aufschlag ?
{
myAufschlag = b + 1; // nächsten Spieler setzen
if (myAufschlag > spielers - 1) // Wert ist grßer als Spieler
{ myAufschlag = 0; } // Dann erster Spieler
}
}
newAufschlag(myAufschlag); // Aufschlag setzen
}
//
void automatikAufschlag() // wird aufgerufen, wenn points-Taste gedrückt wurde
{
if (spieler[0].points + spieler[0].points < 20) // summe points für jedes 2tes Spiel
{
if ((spieler[0].points + spieler[1].points) % 2 == 0) // jedes zweite Spiel auswerten
{
nextAufschlag(); //
}
}
else // Jedes Spiel
{
nextAufschlag();
}
}
void newAufschlag(const byte x)
{
for (byte a = 0; a < spielers; a++)
{spieler[x].aufschlag = false;} // löscht alles
spieler[x].aufschlag = true; // setzt aktuellen
}
void checkKeys()
{
for (byte b = 0; b < spielers; b++)
{
// aufschlag
if (kt.sp[b].aufschlag != oldtable.sp[b].aufschlag)
{
if (kt.sp[b].aufschlag == gedrueckt)
{
newAufschlag(b);
}
oldtable.sp[b].aufschlag = kt.sp[b].aufschlag;
}
// satz Reset
if (kt.sp[b].satzReset != oldtable.sp[b].satzReset)
{
if (kt.sp[b].satzReset == gedrueckt)
{ spieler[b].sets = 0;}
oldtable.sp[b].satzReset = kt.sp[b].satzReset;
}
// satz Minus
if (kt.sp[b].satzMinus != oldtable.sp[b].satzMinus) // Vergleich auf deaktiven Merker
{
if (kt.sp[b].satzMinus == gedrueckt)
{
if (spieler[b].sets > 0) // Nur wenn was auf dem Zähler steht
{ spieler[b].sets--; }
}
oldtable.sp[b].satzMinus = kt.sp[b].satzMinus; // Merker damit nicht weiter gezählt wird
}
// satz Plus
if (kt.sp[b].satzPlus != oldtable.sp[b].satzPlus) // mit Merker
{
if (kt.sp[b].satzPlus == gedrueckt)
{ spieler[b].sets++; }
oldtable.sp[b].satzPlus = kt.sp[b].satzPlus;
}
// spiel Reset
if (kt.sp[b].spielReset != oldtable.sp[b].spielReset)
{
if (kt.sp[b].spielReset == gedrueckt)
{ spieler[b].points = 0; }
oldtable.sp[b].spielReset = kt.sp[b].spielReset;
}
// spiel Minus
if (kt.sp[b].spielMinus != oldtable.sp[b].spielMinus) // mit Merker für Spielstand
{
if (spieler[b].points > 0 && kt.sp[b].spielMinus == gedrueckt)
{ spieler[b].points--; }
oldtable.sp[b].spielMinus = kt.sp[b].spielMinus;
}
// spiel Plus
if (kt.sp[b].spielPlus != oldtable.sp[b].spielPlus) // Siehe Satz
{
if (kt.sp[b].spielPlus == gedrueckt)
{
spieler[b].points++;
automatikAufschlag();
}
oldtable.sp[b].spielPlus = kt.sp[b].spielPlus;
}
}
// EinspielZeit
if (kt.timeEinStart != oldtable.timeEinStart) // Tastenstatus geändert?
{
if (kt.timeEinStart == gedrueckt) //
{
zeit.minute = 2; // Vorbelegung
zeit.sekunde = 0;
zeit.lastTik = millis(); // aktuelle Zeit für timer
}
oldtable.timeEinStart = kt.timeEinStart; // Tastenstatus merken
}
if (kt.timeEinStop != oldtable.timeEinStop)
{
if (kt.timeEinStop == gedrueckt)
{
zeit.minute = 0;
zeit.sekunde = 0;;
}
oldtable.timeEinStop = kt.timeEinStop;
}
// TimeOutZeit
if (kt.timeOutStart != oldtable.timeOutStart)
{
if (kt.timeOutStart == gedrueckt)
{
zeit.minute = 1;
zeit.sekunde = 0;
zeit.lastTik = millis();
}
oldtable.timeOutStart = kt.timeOutStart;
}
if (kt.timeOutStop != oldtable.timeOutStop)
{
if (kt.timeOutStop == gedrueckt)
{
zeit.minute = 0;
zeit.sekunde = 0;;
}
oldtable.timeOutStop = kt.timeOutStop;
}
//
}
Bei jedem point+ wird jetzt geprüft, ob der Aufschlag getauscht wird - mit entsprechender Aktion.
So der Plan.
Hinweis noch am Rande: Den Spielerwechsel hab ich noch nicht. Ich will erstmal, dass der richtig mitzählt.