Turns out you need to drive the YL-3 constantly so implement a disp mgr

This commit is contained in:
Mikko Ahlroth 2019-10-26 13:34:20 +03:00
parent 7ac56da7ce
commit b3a6c2299d
8 changed files with 126 additions and 44 deletions

View file

@ -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(); }

View file

@ -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
View 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
View 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();
};

View file

@ -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");
} }
} }
} }

View file

@ -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();
}; };

View file

@ -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();
const auto length = text.length();
uint8_t i = 0;
if (length > 8) {
i = length - 8;
}
for (; i < length; ++i) {
drawBegin(); drawBegin();
const auto b = char2byte(text.charAt(i)); const auto b = char2byte(c);
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, INDICES[length - 1 - i]); shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, INDICES[index]);
shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, b); shiftOut(YL3_DIO, YL3_SCK, MSBFIRST, b);
drawEnd(); drawEnd();
} }
}
void YL3::drawNumber(const uint32_t score) {
const auto str = String(score);
drawText(str);
}

View file

@ -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