diff --git a/nopeustesti.ino b/nopeustesti.ino index 1e13385..7f34b3d 100644 --- a/nopeustesti.ino +++ b/nopeustesti.ino @@ -2,14 +2,15 @@ #include "src/game_manager.hpp" #include "src/randomiser.hpp" -Debugger* debugger; +Input* input; Randomiser* randomiser; GameManager* game; void setup() { - debugger = new Debugger(9600); + initDebug(9600); + input = new Input(); randomiser = new Randomiser(analogRead(0)); - game = new GameManager(debugger, randomiser); + game = new GameManager(input, randomiser); } void loop() { game->loop(); } diff --git a/src/base_game.cpp b/src/base_game.cpp index a7f19aa..35b2299 100644 --- a/src/base_game.cpp +++ b/src/base_game.cpp @@ -1,4 +1,3 @@ #include "base_game.hpp" -BaseGame::BaseGame(Debugger* debugger, Randomiser* randomiser) - : debugger(debugger), randomiser(randomiser) {} +BaseGame::BaseGame(Randomiser* randomiser) : randomiser(randomiser) {} diff --git a/src/base_game.hpp b/src/base_game.hpp index 7083fa6..6e955fc 100644 --- a/src/base_game.hpp +++ b/src/base_game.hpp @@ -2,6 +2,8 @@ #include "debugger.hpp" #include "randomiser.hpp" +#pragma once + enum class NextOperationType { NOOP, END, ADD_SCORE }; /** @@ -13,11 +15,10 @@ struct NextOperation { }; class BaseGame { - Debugger* debugger; Randomiser* randomiser; public: - BaseGame(Debugger* debugger, Randomiser* randomiser); + BaseGame(Randomiser* randomiser); virtual NextOperation loop() = 0; }; diff --git a/src/config.hpp b/src/config.hpp index 258beb8..c6d78a1 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -12,6 +12,18 @@ const bool DEBUG = true; */ const uint8_t BUTTONS = 4; +/** + * Pins of the buttons, in order from left to right in the case. Leftmost will be 0, and number will + * increase to the right. + */ +const uint8_t BUTTON_PINS[BUTTONS] = {A0, A1, A2, A3}; + +/** + * Debounce delay, i.e. how long a button must be high or low before it is accepted, to reduce + * spurious inputs. + */ +const uint8_t DEBOUNCE_DELAY = 20; + /** * Delay at start of game between beeps, in milliseconds. */ diff --git a/src/debugger.cpp b/src/debugger.cpp index 0133b8e..874a312 100644 --- a/src/debugger.cpp +++ b/src/debugger.cpp @@ -3,9 +3,9 @@ #include #include "config.hpp" -Debugger::Debugger(uint16_t port) : serialPort(port) { Serial.begin(serialPort); } +void initDebug(uint16_t port) { Serial.begin(port); } -void Debugger::print(const String msg, const bool newline) const { +void debugPrint(const String msg, const bool newline) { if (DEBUG) { auto msgCopy = String(msg); diff --git a/src/debugger.hpp b/src/debugger.hpp index ec2c302..b667f52 100644 --- a/src/debugger.hpp +++ b/src/debugger.hpp @@ -2,15 +2,5 @@ #pragma once -/** - * Debugger class providing an interface to the serial port. To disable the debug calls entirely, - * use the DEBUG configuration variable. - */ -class Debugger { - uint16_t serialPort; - - public: - Debugger(uint16_t port); - - void print(const String msg, const bool newline = true) const; -}; +void initDebug(uint16_t port); +void debugPrint(const String msg, const bool newline = true); diff --git a/src/game_manager.cpp b/src/game_manager.cpp index d695547..c35c596 100644 --- a/src/game_manager.cpp +++ b/src/game_manager.cpp @@ -5,9 +5,22 @@ #include "debugger.hpp" #include "randomiser.hpp" -GameManager::GameManager(Debugger* debugger, Randomiser* randomiser) - : debugger(debugger), randomiser(randomiser), state(State::MENU), currentScore(0) { - debugger->print("Initialising new game..."); +GameManager::GameManager(Input* input, Randomiser* randomiser) + : input(input), randomiser(randomiser), state(State::MENU), currentScore(0) { + debugPrint("Initialising new game..."); } -void GameManager::loop() {} +void GameManager::loop() { + static auto prevState = ButtonState::OFF; + + input->process(); + auto status = input->getStatus(); + auto newState = status.buttons[0]; + + if (newState != prevState) { + prevState = newState; + + auto msg = String(static_cast(newState)); + debugPrint(msg, false); + } +} diff --git a/src/game_manager.hpp b/src/game_manager.hpp index 9a247a1..c055d8c 100644 --- a/src/game_manager.hpp +++ b/src/game_manager.hpp @@ -1,17 +1,19 @@ #include "config.hpp" -#include "debugger.hpp" +#include "input.hpp" #include "randomiser.hpp" +#pragma once + enum class State { MENU, INIT, GAME, SCORE }; class GameManager { - Debugger* debugger; + Input* input; Randomiser* randomiser; State state; uint16_t currentScore; public: - GameManager(Debugger* debugger, Randomiser* randomiser); + GameManager(Input* input, Randomiser* randomiser); void loop(); }; diff --git a/src/input.cpp b/src/input.cpp new file mode 100644 index 0000000..f978d17 --- /dev/null +++ b/src/input.cpp @@ -0,0 +1,27 @@ +#include "input.hpp" + +#include +#include "config.hpp" + +Input::Input() : lastChangeTimes{}, currentStates{}, debouncedStates{} { + for (uint8_t i = 0; i < BUTTONS; ++i) { + pinMode(BUTTON_PINS[i], INPUT_PULLUP); + } +} + +void Input::process() { + const auto now = millis(); + for (uint8_t i = 0; i < BUTTONS; ++i) { + // Note that LOW is ON, HIGH is OFF when using pullup + const auto state = (digitalRead(BUTTON_PINS[i]) == LOW) ? ButtonState::ON : ButtonState::OFF; + + if (state != currentStates.buttons[i]) { + currentStates.buttons[i] = state; + lastChangeTimes[i] = now; + } else if (now - lastChangeTimes[i] >= DEBOUNCE_DELAY && state != debouncedStates.buttons[i]) { + debouncedStates.buttons[i] = state; + } + } +} + +const InputStatus& Input::getStatus() const { return debouncedStates; } diff --git a/src/input.hpp b/src/input.hpp new file mode 100644 index 0000000..17b7bf5 --- /dev/null +++ b/src/input.hpp @@ -0,0 +1,26 @@ +#include +#include "config.hpp" + +#pragma once + +enum class ButtonState { OFF, ON }; + +struct InputStatus { + ButtonState buttons[BUTTONS]; +}; + +/** + * Class managing the input coming from buttons, and their debouncing. Also manages setting up the + * proper pins. + */ +class Input { + uint32_t lastChangeTimes[BUTTONS]; + InputStatus currentStates; + InputStatus debouncedStates; + + public: + Input(); + + void process(); + const InputStatus& getStatus() const; +}; diff --git a/src/speed_game.cpp b/src/speed_game.cpp index 95412f3..aa2eda3 100644 --- a/src/speed_game.cpp +++ b/src/speed_game.cpp @@ -2,7 +2,7 @@ #include "base_game.hpp" -SpeedGame::SpeedGame(Debugger* debugger, Randomiser* randomiser) - : BaseGame(debugger, randomiser), waitingBeeps{}, waitingBeepsAmount(0) {} +SpeedGame::SpeedGame(Randomiser* randomiser) + : BaseGame(randomiser), waitingBeeps{}, waitingBeepsAmount(0) {} NextOperation SpeedGame::loop() {} diff --git a/src/speed_game.hpp b/src/speed_game.hpp index c22d6fa..108bd2a 100644 --- a/src/speed_game.hpp +++ b/src/speed_game.hpp @@ -1,5 +1,8 @@ #include "base_game.hpp" #include "config.hpp" +#include "randomiser.hpp" + +#pragma once /** * The default speed test game where you need to press the buttons with an ever increasing speed. @@ -9,6 +12,6 @@ class SpeedGame : BaseGame { uint8_t waitingBeepsAmount; public: - using BaseGame::BaseGame; + SpeedGame(Randomiser* randomiser); NextOperation loop(); };