168 lines
3.2 KiB
C++
168 lines
3.2 KiB
C++
#include "NerfStatTrakConfig.h"
|
|
#include "Globals.h"
|
|
#include "StateHandler.h"
|
|
#include "LowPower.h"
|
|
#include "EEPROM.h"
|
|
|
|
|
|
SegmentDisplay* display;
|
|
Button* buttonA;
|
|
Button* buttonB;
|
|
Button* buttonArmed;
|
|
|
|
uint32_t shots = 0;
|
|
uint32_t hits = 0;
|
|
|
|
unsigned long currentTime;
|
|
AbstractStateHandler* currentState;
|
|
|
|
byte shotCounterOffset;
|
|
byte hitCounterOffset;
|
|
|
|
|
|
#define counterTreshold (uint32_t)10000
|
|
uint32_t lastShotCounterIteration;
|
|
uint32_t lastHitCounterIteration;
|
|
|
|
void setCurrentState(AbstractStateHandler* value)
|
|
{
|
|
buttonA->block();
|
|
buttonB->block();
|
|
|
|
currentState = value;
|
|
currentState->setup();
|
|
}
|
|
|
|
|
|
void update()
|
|
{
|
|
currentTime = millis();
|
|
|
|
buttonA->update(currentTime);
|
|
buttonB->update(currentTime);
|
|
buttonArmed->update(currentTime);
|
|
|
|
// Count the shot no matter which state we're in
|
|
if (buttonArmed->changed() && !buttonArmed->pressed())
|
|
addShot();
|
|
}
|
|
|
|
|
|
void wakeUp()
|
|
{
|
|
}
|
|
|
|
|
|
void sleep()
|
|
{
|
|
display->clear();
|
|
|
|
// Uses RocketScream's Low-Power library
|
|
// https://github.com/rocketscream/Low-Power
|
|
uint32_t interrupt = digitalPinToInterrupt(NerfButtonWakeUp);
|
|
|
|
attachInterrupt(interrupt, wakeUp, NerfButtonWakeUpState);
|
|
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
|
|
detachInterrupt(interrupt);
|
|
|
|
|
|
currentTime = millis();
|
|
|
|
// The button triggers the wake-up, so block the first release after
|
|
if (NerfButtonWakeUp == NerfButtonA)
|
|
{
|
|
buttonA->update(currentTime);
|
|
buttonA->block();
|
|
}
|
|
|
|
if (NerfButtonWakeUp == NerfButtonB)
|
|
{
|
|
buttonB->update(currentTime);
|
|
buttonB->block();
|
|
}
|
|
}
|
|
|
|
|
|
#define counterLocation(offset) 2 + (offset * sizeof(uint32_t))
|
|
|
|
void readCounters()
|
|
{
|
|
shotCounterOffset = EEPROM.read(0);
|
|
hitCounterOffset = EEPROM.read(1);
|
|
|
|
EEPROM.get(counterLocation(shotCounterOffset), shots);
|
|
EEPROM.get(counterLocation(hitCounterOffset), hits);
|
|
|
|
lastShotCounterIteration = shots / counterTreshold;
|
|
lastHitCounterIteration = hits / counterTreshold;
|
|
}
|
|
|
|
|
|
void setShots(uint32_t value)
|
|
{
|
|
shots = value;
|
|
|
|
uint32_t newShotCounterIteration = shots / counterTreshold;
|
|
if (newShotCounterIteration != lastShotCounterIteration || value == 0)
|
|
{
|
|
shotCounterOffset++;
|
|
if (counterLocation(shotCounterOffset) > EEPROM.length() - sizeof(uint32_t))
|
|
{
|
|
shotCounterOffset = 0;
|
|
if (shotCounterOffset == hitCounterOffset)
|
|
shotCounterOffset++;
|
|
}
|
|
|
|
EEPROM.write(0, shotCounterOffset);
|
|
lastShotCounterIteration = newShotCounterIteration;
|
|
}
|
|
|
|
EEPROM.write(counterLocation(shotCounterOffset), shots);
|
|
}
|
|
|
|
|
|
void addShot()
|
|
{
|
|
setShots(shots + 1);
|
|
}
|
|
|
|
|
|
void setHits(uint32_t value)
|
|
{
|
|
hits = value;
|
|
|
|
uint32_t newHitCounterIteration = hits / counterTreshold;
|
|
if (newHitCounterIteration != lastHitCounterIteration || value == 0)
|
|
{
|
|
hitCounterOffset++;
|
|
if (counterLocation(hitCounterOffset) > EEPROM.length() - sizeof(uint32_t))
|
|
{
|
|
hitCounterOffset = 0;
|
|
if (hitCounterOffset == shotCounterOffset)
|
|
hitCounterOffset++;
|
|
}
|
|
|
|
EEPROM.write(1, hitCounterOffset);
|
|
lastHitCounterIteration = newHitCounterIteration;
|
|
}
|
|
|
|
EEPROM.write(counterLocation(hitCounterOffset), hits);
|
|
}
|
|
|
|
|
|
void addHit()
|
|
{
|
|
setHits(hits + 1);
|
|
}
|
|
|
|
|
|
void resetShots()
|
|
{
|
|
setShots(0);
|
|
}
|
|
|
|
|
|
void resetHits()
|
|
{
|
|
setHits(0);
|
|
} |