#include <FastLED.h>
#define NUM_LEDS 212
//****************************
#define DATA_PIN 6
const char* zero = "####"
"#..#"
"#..#"
"#..#"
"#..#"
"#..#"
"####";
const char* one = "...#"
"...#"
"...#"
"...#"
"...#"
"...#"
"...#";
const char* two = "####"
"...#"
"...#"
"####"
"#..."
"#..."
"####";
const char* three = "####"
"...#"
"...#"
"####"
"...#"
"...#"
"####";
const char* four = "#..#"
"#..#"
"#..#"
"####"
"...#"
"...#"
"...#";
const char* five = "####"
"#..."
"#..."
"####"
"...#"
"...#"
"####";
const char* six = "#..."
"#..."
"#..."
"####"
"#..#"
"#..#"
"####";
const char* seven = "####"
"...#"
"...#"
"...#"
"...#"
"...#"
"...#";
const char* eight = "####"
"#..#"
"#..#"
"####"
"#..#"
"#..#"
"####";
const char* nine = "####"
"#..#"
"#..#"
"####"
"...#"
"...#"
"####";
const char* numberConfigs[] {zero, one, two, three, four, five, six, seven, eight, nine};
struct DigitElement
{
int baseOffset;
bool hasOneHundred;
int segmentedDigitCount;
};
struct IndicatorElement
{
int baseOffset;
int lightCount;
};
DigitElement homeScore = {0, true, 2};
DigitElement visitorScore = {127, true, 2};
DigitElement timeMinutes = {47, false, 2};
DigitElement timeSeconds = {87, false, 2};
DigitElement period = {183, false, 1};
IndicatorElement homeBonus = {209, 3};
IndicatorElement visitorBonus = {174, 3};
IndicatorElement homePosession = {203, 6};
IndicatorElement visitorPosession = {177, 6};
CRGB leds[NUM_LEDS];
CRGB onColor = CRGB::White;
CRGB offColor = CRGB::Black;
void stringToDigit(char* str, int ledStartIndex)
{
stringToDigit(str, ledStartIndex, onColor);
}
void stringToDigit(char* str, int ledStartIndex, CRGB colorOverride)
{
leds[ledStartIndex] = str[0] == '#' ? colorOverride : offColor;
leds[ledStartIndex+1] = str[1] == '#' ? colorOverride : offColor;
leds[ledStartIndex+2] = str[2] == '#' ? colorOverride : offColor;
leds[ledStartIndex+3] = str[3] == '#' ? colorOverride : offColor;
leds[ledStartIndex+4] = str[7] == '#' ? colorOverride : offColor;
leds[ledStartIndex+5] = str[4] == '#' ? colorOverride : offColor;
leds[ledStartIndex+6] = str[8] == '#' ? colorOverride : offColor;
leds[ledStartIndex+7] = str[11] == '#' ? colorOverride : offColor;
leds[ledStartIndex+8] = str[15] == '#' ? colorOverride : offColor;
leds[ledStartIndex+9] = str[14] == '#' ? colorOverride : offColor;
leds[ledStartIndex+10] = str[13] == '#' ? colorOverride : offColor;
leds[ledStartIndex+11] = str[12] == '#' ? colorOverride : offColor;
leds[ledStartIndex+12] = str[16] == '#' ? colorOverride : offColor;
leds[ledStartIndex+13] = str[19] == '#' ? colorOverride : offColor;
leds[ledStartIndex+14] = str[23] == '#' ? colorOverride : offColor;
leds[ledStartIndex+15] = str[20] == '#' ? colorOverride : offColor;
leds[ledStartIndex+16] = str[24] == '#' ? colorOverride : offColor;
leds[ledStartIndex+17] = str[25] == '#' ? colorOverride : offColor;
leds[ledStartIndex+18] = str[26] == '#' ? colorOverride : offColor;
leds[ledStartIndex+19] = str[27] == '#' ? colorOverride : offColor;
}
//*****************************************************
void updateDigit(DigitElement el, int value)
{
updateDigit(el, value, onColor);
}
void updateDigit(DigitElement el, int value, CRGB colorOverride)
{
int currentRoot = el.baseOffset;
if (el.hasOneHundred)
{
CRGB hundred = (value > 99) ? colorOverride : offColor;
for (int i = currentRoot; i < currentRoot + 7; i++)
{
leds[i] = hundred;
}
currentRoot += 7;
}
if (el.segmentedDigitCount > 1)
{
int tensIndex = (value / 10) % 10;
stringToDigit(numberConfigs[tensIndex], currentRoot, colorOverride);
currentRoot += 20;
}
int onesIndex = (value % 10);
stringToDigit(numberConfigs[onesIndex], currentRoot, colorOverride);
}
void updateIndicator(IndicatorElement el, bool value)
{
updateIndicator(el, value, onColor);
}
void updateIndicator(IndicatorElement el, bool value, CRGB colorOverride)
{
for (int i = el.baseOffset; i < el.baseOffset + el.lightCount; i++) {
leds[i] = value ? colorOverride : offColor;
}
}
//********************************************************
int nPeriod = 1;
int seconds = 0;
int nHomeScore = 0;
int nVisitorScore = 0;
bool bTimeRunning = false;
int bonus = 0; // -1 home; 0 none; 1 visitors
bool posession = 0; // 0 home; 1 visitors
void updateScoreboard()
{
nHomeScore = constrain(nHomeScore, 0, 199);
nVisitorScore = constrain(nVisitorScore, 0, 199);
nPeriod = constrain(nPeriod, 0, 9);
seconds = constrain(seconds, 0, 3600);
int minutesCalc = seconds / 60;
int secondsCalc = seconds % 60;
updateDigit(homeScore, nHomeScore, CRGB::DarkRed);
updateDigit(visitorScore, nVisitorScore, CRGB::DarkRed);
updateDigit(period, nPeriod, CRGB::LimeGreen);
updateDigit(timeMinutes, minutesCalc, CRGB::FairyLight);
updateDigit(timeSeconds, secondsCalc, CRGB::FairyLight);
updateIndicator(homePosession, posession == 0);
updateIndicator(visitorPosession, posession == 1);
updateIndicator(homeBonus, bonus == -1);
updateIndicator(visitorBonus, bonus == 1);
FastLED.show();
}
void HomeScoreUp1() {
nHomeScore++;
}
void HomeScoreReset() {
nHomeScore = 0;
}
void HomeScoreDown1() {
nHomeScore--;
}
void PeriodUp() {
nPeriod++;
if (nPeriod > 4)
{
nPeriod = 1;
}
}
void VisitorScoreDown1() {
nVisitorScore--;
}
void VisitorScoreReset() {
nVisitorScore = 0;
}
void VisitorScoreUp1() {
nVisitorScore++;
}
void HomeBonus() {
bonus = (bonus == -1) ? 0 : -1;
}
void HomePos() {
posession = 0;
}
void VisitorPos() {
posession = 1;
}
void VisitorBonus() {
bonus = (bonus == 1) ? 0 : 1;
}
void StartStopTimer() {
bTimeRunning = !bTimeRunning;
}
void TimeDn1() {
seconds--;
}
void TimeDn10() {
seconds-=10;
}
void TimeDn60() {
seconds-=60;
}
void TimeUp60() {
seconds+=60;
}
void TimeUp10() {
seconds+=10;
}
void TimeUp1() {
seconds++;
}
void TimerSet12() {
seconds = 720;
}
void TimerSet10() {
seconds = 600;
}
void TimerSet0() {
seconds = 0;
}
void TimerSet2() {
seconds = 120;
}
void TimerSet20() {
seconds = 1200;
}
void Buzzer() {
// TODO:
Serial.println("Zzzzzt!");
}
//********************************************************
void setup() {
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
Serial.begin(9600);
// TEMP FOR TESTING
TimerSet2();
StartStopTimer();
//_________________
}
void loop() {
// TEMP FOR TESTING
if (nHomeScore == 0)
{
nHomeScore = 199;
}
nVisitorScore = 199 - nHomeScore;
HomeScoreDown1();
PeriodUp();
//_________________
if (bTimeRunning)
{
seconds--;
if (seconds == 0)
{
bTimeRunning = false;
Buzzer();
}
}
updateScoreboard();
delay(1000);
}
Shot timer.
Home Team Score.
Visitor Team Score.
Current period.
Visitor Posession.
Home Team Posession.
Home Team Bonus.
Visitor Team Bonus.