#include <Adafruit_NeoPixel.h>
#include <TM1637.h>
#define NUM_RINGS 4
#define RESET_BTN 12
//display pins
#define DISPLAY_CLK A3
#define DISPLAY_DIO A4
TM1637 display;
//leds per ring
#define RING1 8
#define RING2 16
#define RING3 24
#define RING4 32
#define LED_PIN A5
#define LED_COUNT RING1+RING2+RING3+RING4
Adafruit_NeoPixel rings(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
const byte buttonPins[NUM_RINGS] = {2, 3, 4, 5};
const byte pointValues[NUM_RINGS] = {100, 50, 25, 10};
unsigned long buttonTimes[NUM_RINGS];
const unsigned long intervalDebounce = 50ul;
unsigned long ringTimes[NUM_RINGS];
const unsigned long intervalLedOn = 1000ul;
byte buttonStates[NUM_RINGS] = {1, 1, 1, 1};
byte ringStates[NUM_RINGS] = {1, 1, 1, 1};
volatile uint32_t totalPoints;
unsigned long lastReset;
byte stateReset = 1;
void setup()
{
Serial.begin(115200);
//init detection buttons
for (int i = 0; i < NUM_RINGS; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
//init reset button
pinMode(RESET_BTN, INPUT_PULLUP);
//init the rings
rings.begin();
rings.show();
rings.setBrightness(255);
//light up rings..
int i;
for (i = 0; i < 8; i++) {
rings.setPixelColor(i, rings.Color(255, 0, 0));
}
rings.show();
delay(500);
for (i = 8; i < 24; i++) {
rings.setPixelColor(i, rings.Color(0, 255, 0));
}
rings.show();
delay(500);
for (i = 24; i < 48; i++) {
rings.setPixelColor(i, rings.Color(0, 0, 255));
}
rings.show();
delay(500);
for (i = 48; i < 80; i++) {
rings.setPixelColor(i, rings.Color(255, 255, 0));
}
rings.show();
//init scoreboard display
display.begin(DISPLAY_CLK, DISPLAY_DIO, 4);
display.displayClear();
display.displayInt(0);
delay(500);
}
void loop()
{
unsigned long now = millis();
for (int i = 0; i < NUM_RINGS; i++) {
if (now - buttonTimes[i] >= intervalDebounce) {
byte val = digitalRead(buttonPins[i]);
if (val != buttonStates[i]) {
buttonTimes[i] = now;//start debouncing..
buttonStates[i] = val;
if (val == LOW) {
totalPoints += pointValues[i];//add the points based on preset values
Serial.print("Hit Button: "); Serial.println(i + 1);
Serial.print("Total Points: "); Serial.println(totalPoints);
switch (i) {
case 0: {
for (int i = 0; i < 8; i++) {
rings.setPixelColor(i, rings.Color(255, 0, 0));
}
rings.show();
} break;
case 1: {
for (int i = 8; i < 24; i++) {
rings.setPixelColor(i, rings.Color(0, 255, 0));
}
rings.show();
} break;
case 2: {
for (int i = 24; i < 48; i++) {
rings.setPixelColor(i, rings.Color(0, 0, 255));
}
rings.show();
} break;
case 3: {
for (int i = 48; i < 80; i++) {
rings.setPixelColor(i, rings.Color(255, 255, 0));
}
rings.show();
} break;
}
ringTimes[i] = now; //start led timer
ringStates[i] = 1;
display.displayInt(totalPoints);
}
}
}
//see if it's time to turn off a ring
if (now - ringTimes[i] >= intervalLedOn && ringStates[i] == 1) {
ringStates[i] = 0;
switch (i) {
case 0: {
for (int i = 0; i < 8; i++) {
rings.setPixelColor(i, rings.Color(0, 0, 0));
}
rings.show();
} break;
case 1: {
for (int i = 8; i < 24; i++) {
rings.setPixelColor(i, rings.Color(0, 0, 0));
}
rings.show();
} break;
case 2: {
for (int i = 24; i < 48; i++) {
rings.setPixelColor(i, rings.Color(0, 0, 0));
}
rings.show();
} break;
case 3: {
for (int i = 48; i < 80; i++) {
rings.setPixelColor(i, rings.Color(0, 0, 0));
}
rings.show();
} break;
}
}
}
//handle reset button
if (now - lastReset >= intervalDebounce) {
byte r = digitalRead(RESET_BTN);
if (r != stateReset) {
lastReset = now;
stateReset = r;
if (stateReset == LOW) {
totalPoints = 0;
display.displayInt(0);
}
}
}
}