Turns out you need to drive the YL-3 constantly so implement a disp mgr
This commit is contained in:
parent
7ac56da7ce
commit
b3a6c2299d
8 changed files with 126 additions and 44 deletions
|
@ -1,18 +1,19 @@
|
||||||
#include "src/debugger.hpp"
|
#include "src/debugger.hpp"
|
||||||
|
#include "src/display_manager.hpp"
|
||||||
#include "src/game_manager.hpp"
|
#include "src/game_manager.hpp"
|
||||||
#include "src/randomiser.hpp"
|
#include "src/randomiser.hpp"
|
||||||
#include "src/yl3.hpp"
|
|
||||||
|
|
||||||
Input* input;
|
Input* input;
|
||||||
Randomiser* randomiser;
|
Randomiser* randomiser;
|
||||||
GameManager* game;
|
GameManager* game;
|
||||||
|
DisplayManager* displayManager;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
initDebug(9600);
|
initDebug(9600);
|
||||||
YL3::initDisplay();
|
|
||||||
input = new Input();
|
input = new Input();
|
||||||
randomiser = new Randomiser(analogRead(0));
|
randomiser = new Randomiser(analogRead(0));
|
||||||
game = new GameManager(input, randomiser);
|
displayManager = new DisplayManager();
|
||||||
|
game = new GameManager(input, randomiser, displayManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() { game->loop(); }
|
void loop() { game->loop(); }
|
||||||
|
|
|
@ -50,7 +50,7 @@ const auto DELAY_DECREMENT = [](uint16_t delay) -> uint16_t {
|
||||||
/**
|
/**
|
||||||
* Maximum amount of beeps you can be "behind" before the game is stopped.
|
* Maximum amount of beeps you can be "behind" before the game is stopped.
|
||||||
*/
|
*/
|
||||||
const uint8_t MAX_WAITING = 10;
|
const uint8_t MAX_WAITING = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RCK (latch) pin of YL3 display.
|
* RCK (latch) pin of YL3 display.
|
||||||
|
|
49
src/display_manager.cpp
Normal file
49
src/display_manager.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include "display_manager.hpp"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "yl3.hpp"
|
||||||
|
|
||||||
|
DisplayManager::DisplayManager() : currentIndex(0), currentDisplay(""), currentDisplayLength(0) {
|
||||||
|
YL3::initDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayManager::clearDisplay() {
|
||||||
|
YL3::clearDisplay();
|
||||||
|
currentDisplay = "";
|
||||||
|
currentIndex = 0;
|
||||||
|
currentDisplayLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayManager::drawText(const String text) {
|
||||||
|
clearDisplay();
|
||||||
|
|
||||||
|
const auto length = text.length();
|
||||||
|
currentDisplay = text;
|
||||||
|
currentDisplayLength = length;
|
||||||
|
currentIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayManager::drawNumber(const uint32_t number) {
|
||||||
|
const auto str = String(number);
|
||||||
|
drawText(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayManager::loop() {
|
||||||
|
if (currentDisplayLength == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char c = currentDisplay.charAt(currentIndex);
|
||||||
|
|
||||||
|
uint8_t i = currentIndex;
|
||||||
|
if (currentDisplayLength > 8) {
|
||||||
|
i = currentIndex - 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
YL3::drawChar(currentDisplayLength - 1 - i, c);
|
||||||
|
|
||||||
|
++currentIndex;
|
||||||
|
if (currentIndex >= currentDisplayLength) {
|
||||||
|
currentIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
41
src/display_manager.hpp
Normal file
41
src/display_manager.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display manager for the YL3 8x7-segment display.
|
||||||
|
*
|
||||||
|
* The YL3 can only display one digit at a time, in as many positions as needed. Usually though we
|
||||||
|
* need to display many digits in different positions. This display manager will keep in memory the
|
||||||
|
* displayable text and display one digit at a time, flickering the display fast enough so that the
|
||||||
|
* user doesn't notice.
|
||||||
|
*/
|
||||||
|
class DisplayManager {
|
||||||
|
uint8_t currentIndex;
|
||||||
|
String currentDisplay;
|
||||||
|
uint8_t currentDisplayLength;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DisplayManager();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear display entirely.
|
||||||
|
*/
|
||||||
|
void clearDisplay();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw text on the screen, right aligned. Text longer than 8 characters will be truncated.
|
||||||
|
*/
|
||||||
|
void drawText(const String text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a number on the screen, right aligned. Numbers larger than can fit on the display will be
|
||||||
|
* truncated.
|
||||||
|
*/
|
||||||
|
void drawNumber(const uint32_t number);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw character and advance to next one for next loop.
|
||||||
|
*/
|
||||||
|
void loop();
|
||||||
|
};
|
|
@ -4,30 +4,36 @@
|
||||||
#include "base_game.hpp"
|
#include "base_game.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "debugger.hpp"
|
#include "debugger.hpp"
|
||||||
|
#include "display_manager.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
#include "randomiser.hpp"
|
#include "randomiser.hpp"
|
||||||
#include "speed_game.hpp"
|
#include "speed_game.hpp"
|
||||||
#include "yl3.hpp"
|
|
||||||
|
|
||||||
GameManager::GameManager(Input* input, Randomiser* randomiser)
|
GameManager::GameManager(Input* input, Randomiser* randomiser, DisplayManager* displayManager)
|
||||||
: input(input), randomiser(randomiser), state(State::GAME), currentScore(0) {
|
: input(input),
|
||||||
|
randomiser(randomiser),
|
||||||
|
displayManager(displayManager),
|
||||||
|
state(State::GAME),
|
||||||
|
currentScore(0) {
|
||||||
debugPrint("Initialising new game...");
|
debugPrint("Initialising new game...");
|
||||||
currentGame = new SpeedGame(randomiser);
|
currentGame = new SpeedGame(randomiser);
|
||||||
YL3::clearDisplay();
|
displayManager->clearDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameManager::loop() {
|
void GameManager::loop() {
|
||||||
|
displayManager->loop();
|
||||||
|
|
||||||
if (state == State::GAME) {
|
if (state == State::GAME) {
|
||||||
auto nextOp = currentGame->loop();
|
auto nextOp = currentGame->loop();
|
||||||
|
|
||||||
if (nextOp.type == NextOperationType::ADD_SCORE) {
|
if (nextOp.type == NextOperationType::ADD_SCORE) {
|
||||||
currentScore += nextOp.scoreToAdd;
|
currentScore += nextOp.scoreToAdd;
|
||||||
debugPrint("Added score!");
|
debugPrint("Added score!");
|
||||||
YL3::drawNumber(currentScore);
|
displayManager->drawNumber(currentScore);
|
||||||
} else if (nextOp.type == NextOperationType::END) {
|
} else if (nextOp.type == NextOperationType::END) {
|
||||||
debugPrint("Game ended.");
|
debugPrint("Game ended.");
|
||||||
state = State::SCORE;
|
state = State::SCORE;
|
||||||
YL3::drawText("END");
|
displayManager->drawText("END");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "base_game.hpp"
|
#include "base_game.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include "display_manager.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
#include "randomiser.hpp"
|
#include "randomiser.hpp"
|
||||||
|
|
||||||
|
@ -10,12 +11,13 @@ enum class State { MENU, INIT, GAME, SCORE };
|
||||||
class GameManager {
|
class GameManager {
|
||||||
Input* input;
|
Input* input;
|
||||||
Randomiser* randomiser;
|
Randomiser* randomiser;
|
||||||
|
DisplayManager* displayManager;
|
||||||
State state;
|
State state;
|
||||||
uint16_t currentScore;
|
uint16_t currentScore;
|
||||||
BaseGame* currentGame;
|
BaseGame* currentGame;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GameManager(Input* input, Randomiser* randomiser);
|
GameManager(Input* input, Randomiser* randomiser, DisplayManager* displayManager);
|
||||||
|
|
||||||
void loop();
|
void loop();
|
||||||
};
|
};
|
||||||
|
|
30
src/yl3.cpp
30
src/yl3.cpp
|
@ -28,31 +28,15 @@ void YL3::initDisplay() {
|
||||||
|
|
||||||
void YL3::clearDisplay() {
|
void YL3::clearDisplay() {
|
||||||
drawBegin();
|
drawBegin();
|
||||||
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, 0b11111111);
|
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, ALL);
|
||||||
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, EMPTY);
|
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, EMPTY);
|
||||||
drawEnd();
|
drawEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void YL3::drawText(const String text) {
|
void YL3::drawChar(const uint8_t index, const char c) {
|
||||||
clearDisplay();
|
drawBegin();
|
||||||
|
const auto b = char2byte(c);
|
||||||
const auto length = text.length();
|
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, INDICES[index]);
|
||||||
|
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, b);
|
||||||
uint8_t i = 0;
|
drawEnd();
|
||||||
if (length > 8) {
|
|
||||||
i = length - 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i < length; ++i) {
|
|
||||||
drawBegin();
|
|
||||||
const auto b = char2byte(text.charAt(i));
|
|
||||||
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, INDICES[length - 1 - i]);
|
|
||||||
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, b);
|
|
||||||
drawEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void YL3::drawNumber(const uint32_t score) {
|
|
||||||
const auto str = String(score);
|
|
||||||
drawText(str);
|
|
||||||
}
|
}
|
||||||
|
|
19
src/yl3.hpp
19
src/yl3.hpp
|
@ -35,9 +35,9 @@ const byte CHARS[] = {
|
||||||
0b10010000, // 9
|
0b10010000, // 9
|
||||||
0b10001000, // A
|
0b10001000, // A
|
||||||
0b10000011, // B
|
0b10000011, // B
|
||||||
0b10111001, // C
|
0b11000110, // C
|
||||||
0b10100001, // D
|
0b10100001, // D
|
||||||
0b10110000, // E
|
0b10000110, // E
|
||||||
0b10001110, // F
|
0b10001110, // F
|
||||||
0b10000010, // G
|
0b10000010, // G
|
||||||
0b10001001, // H
|
0b10001001, // H
|
||||||
|
@ -68,6 +68,11 @@ const byte CHARS[] = {
|
||||||
const byte INDICES[] = {0b10000000, 0b01000000, 0b00100000, 0b00010000,
|
const byte INDICES[] = {0b10000000, 0b01000000, 0b00100000, 0b00010000,
|
||||||
0b00001000, 0b00000100, 0b00000010, 0b00000001};
|
0b00001000, 0b00000100, 0b00000010, 0b00000001};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index that refers to all positions.
|
||||||
|
*/
|
||||||
|
const byte ALL = 0b11111111;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty byte to clear display.
|
* Empty byte to clear display.
|
||||||
*/
|
*/
|
||||||
|
@ -99,14 +104,8 @@ void initDisplay();
|
||||||
void clearDisplay();
|
void clearDisplay();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw text on the screen, right aligned. Text longer than 8 characters will be truncated.
|
* Draw character on the screen in given index.
|
||||||
*/
|
*/
|
||||||
void drawText(const String text);
|
void drawChar(uint8_t index, const char c);
|
||||||
|
|
||||||
/**
|
|
||||||
* Draw a number on the screen, right aligned. Numbers larger than can fit on the display will be
|
|
||||||
* truncated.
|
|
||||||
*/
|
|
||||||
void drawNumber(const uint32_t score);
|
|
||||||
|
|
||||||
}; // namespace YL3
|
}; // namespace YL3
|
||||||
|
|
Reference in a new issue