99 lines
2.6 KiB
C++
99 lines
2.6 KiB
C++
/*
|
|
_ __ _ _ __ _____ ___
|
|
| |/ _ _| |__ | |/ /__ _ _ __|_ _|_ _|_ __ ___ ___ _ __
|
|
| ' | | | | '_ \| ' // _` | '__ | | | || '_ ` _ \ / _ | '__|
|
|
| . | |_| | |_) | . | (_| | | | | | || | | | | | __| |
|
|
|_|\_\__,_|_.__/|_|\_\__,_|_| |_| |___|_| |_| |_|\___|_|
|
|
|
|
*/
|
|
#include "Arduino.h"
|
|
|
|
#include <Wire.h>
|
|
#include <LiquidCrystal_I2C.h>
|
|
|
|
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
|
|
|
|
#define PIN_RESET 2
|
|
#define PIN_CAR1 3
|
|
#define PIN_LED LED_BUILTIN
|
|
#define DISPLAY_LINES 4
|
|
|
|
// assume all cars are on sequential digital pins
|
|
#define PIN_CAR_STARTING 3
|
|
|
|
// number of cars (4 max)
|
|
#define CAR_COUNT 4
|
|
|
|
// buffer for the LCD line
|
|
char buffer[40];
|
|
|
|
void setup()
|
|
{
|
|
pinMode(PIN_RESET, INPUT_PULLUP);
|
|
pinMode(PIN_LED, OUTPUT);
|
|
|
|
// initialize each car PIN
|
|
for(short i=0; i<CAR_COUNT; i++) {
|
|
pinMode(PIN_CAR_STARTING + i, INPUT_PULLUP);
|
|
}
|
|
|
|
// initialize LCD
|
|
lcd.begin(20, DISPLAY_LINES);
|
|
lcd.backlight();
|
|
lcd.setCursor(1,1);
|
|
lcd.print("Jeff's Inept");
|
|
lcd.setCursor(6,2);
|
|
lcd.print("Kub Kar Timer");
|
|
}
|
|
|
|
#define STATE_READY 1
|
|
#define STATE_RUNNING 2
|
|
|
|
unsigned long startTime; // start time in ms
|
|
unsigned short state = 0;
|
|
unsigned short place = 0;
|
|
bool finished[CAR_COUNT];
|
|
|
|
void loop()
|
|
{
|
|
|
|
if (digitalRead(PIN_RESET) == LOW) {
|
|
if (state != STATE_READY) {
|
|
digitalWrite(PIN_LED, HIGH);
|
|
state = STATE_READY;
|
|
lcd.clear();
|
|
lcd.setCursor(0,0);
|
|
lcd.print("Ready...");
|
|
}
|
|
} else {
|
|
if (state == STATE_READY) {
|
|
digitalWrite(PIN_LED, LOW);
|
|
state = STATE_RUNNING;
|
|
lcd.setCursor(0,0);
|
|
lcd.print("Running!");
|
|
startTime = millis();
|
|
for(int i=0; i<CAR_COUNT; i++) {
|
|
finished[i] = false;
|
|
}
|
|
place = 0;
|
|
}
|
|
if (state == STATE_RUNNING) {
|
|
unsigned long elapsedTime = millis() - startTime;
|
|
for(short i = 0; i<CAR_COUNT; i++) {
|
|
if (!finished[i] && digitalRead(PIN_CAR_STARTING + i) == LOW) {
|
|
place++;
|
|
finished[i] = true;
|
|
if (place <= DISPLAY_LINES) {
|
|
// NOTE: Some concern LCD writing takes enough cycles it'll potentially miss other car finishing
|
|
// events. Alternative is to draw only once all cars finish but then we need a timeout to handle
|
|
// missing or non-finishing cars. Who wants to wait for results?
|
|
lcd.setCursor(0,place-1);
|
|
sprintf(buffer, "%d%s: CAR%d @ %0.2fs", place, place==1?"st":(place==2?"nd":(place==3?"rd":"th")) , i+1, elapsedTime/1000.0);
|
|
lcd.print(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
} |