Public Access
110 lines
3.2 KiB
C++
110 lines
3.2 KiB
C++
// Portal-style end-credits show for the EL512.256-H: timed song text typed into
|
|||
|
|
// a console on the left, credits typed top right, ASCII art bottom right.
|
||
|
|
//
|
||
|
|
// Framework-agnostic: draws straight into an EL512Panel with the built-in 5x7
|
||
|
|
// font, so the PlatformIO demo (src/still_alive) and the ESPHome component use
|
||
|
|
// the same code. The content is in still_alive_data.h, generated by
|
||
|
|
// tools/import_still_alive.py.
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <stddef.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
|
||
|
|
class EL512Panel;
|
||
|
|
|
||
|
|
namespace el512sa {
|
||
|
|
|
||
|
|
enum : uint8_t {
|
||
|
|
STEP_NEWLINE = 1 << 0, // start a new line after the text is typed
|
||
|
|
STEP_CLEAR = 1 << 1, // clear the console before typing
|
||
|
|
};
|
||
|
|
|
||
|
|
// One timed piece of console text. Steps are sorted by startMs.
|
||
|
|
struct LyricStep {
|
||
|
|
uint32_t startMs; // from the start of the show
|
||
|
|
uint16_t durMs; // the text is typed out evenly over this time
|
||
|
|
uint8_t flags;
|
||
|
|
int8_t art; // picture to show (index into ARTS), or ART_KEEP
|
||
|
|
const char *text;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct Art {
|
||
|
|
const char *const *lines;
|
||
|
|
uint8_t count;
|
||
|
|
};
|
||
|
|
|
||
|
|
static constexpr int8_t ART_KEEP = -1; // leave the current picture
|
||
|
|
static constexpr int8_t ART_NONE = 0; // ARTS[0] is always the empty picture
|
||
|
|
|
||
|
|
// Fixed-size character console in the 5x7 font (6x8 cells), optionally inside a
|
||
|
|
// dashed frame. Text wraps at the right edge and scrolls up past the bottom row.
|
||
|
|
class TextBox {
|
||
|
|
public:
|
||
|
|
static constexpr uint8_t MAX_COLS = 48;
|
||
|
|
static constexpr uint8_t MAX_ROWS = 32;
|
||
|
|
static constexpr int16_t PAD = 4;
|
||
|
|
static constexpr int16_t CHAR_W = 6;
|
||
|
|
static constexpr int16_t CHAR_H = 8;
|
||
|
|
|
||
|
|
TextBox(int16_t x, int16_t y, int16_t w, int16_t h);
|
||
|
|
|
||
|
|
uint8_t cols() const { return cols_; }
|
||
|
|
uint8_t rows() const { return rows_; }
|
||
|
|
|
||
|
|
void clear();
|
||
|
|
void put(char c);
|
||
|
|
void print(const char *s);
|
||
|
|
void draw(EL512Panel &panel, bool cursor, bool frame = true) const;
|
||
|
|
|
||
|
|
private:
|
||
|
|
void newLine();
|
||
|
|
|
||
|
|
int16_t x_, y_, w_, h_;
|
||
|
|
uint8_t cols_, rows_;
|
||
|
|
uint8_t row_ = 0, col_ = 0;
|
||
|
|
char text_[MAX_ROWS][MAX_COLS + 1];
|
||
|
|
};
|
||
|
|
|
||
|
|
class StillAlivePlayer {
|
||
|
|
public:
|
||
|
|
static constexpr uint32_t START_DELAY_MS = 1000; // after start()
|
||
|
|
static constexpr uint32_t CURSOR_BLINK_MS = 300;
|
||
|
|
static constexpr uint32_t HOLD_MS = 10000; // after the last step, before finished()
|
||
|
|
|
||
|
|
StillAlivePlayer();
|
||
|
|
|
||
|
|
// Restart the show; it begins START_DELAY_MS after nowMs.
|
||
|
|
void start(uint32_t nowMs);
|
||
|
|
// Advance to nowMs; true if the screen changed (text, picture or cursor).
|
||
|
|
bool update(uint32_t nowMs);
|
||
|
|
// Draw the whole show; the caller clears the panel first and shows it after.
|
||
|
|
void draw(EL512Panel &panel) const;
|
||
|
|
// True once the last step has been typed and HOLD_MS has passed.
|
||
|
|
bool finished(uint32_t nowMs) const;
|
||
|
|
// When to start the music, relative to start().
|
||
|
|
static uint32_t songStartMs();
|
||
|
|
|
||
|
|
private:
|
||
|
|
bool updateLyrics(uint32_t t, uint32_t nowMs);
|
||
|
|
bool updateCredits(uint32_t t);
|
||
|
|
void showArt(int8_t id);
|
||
|
|
|
||
|
|
TextBox lyrics_;
|
||
|
|
TextBox credits_;
|
||
|
|
TextBox art_;
|
||
|
|
uint32_t showStart_ = 0;
|
||
|
|
size_t step_ = 0;
|
||
|
|
size_t charIdx_ = 0;
|
||
|
|
bool stepStarted_ = false;
|
||
|
|
bool done_ = false;
|
||
|
|
uint32_t doneAt_ = 0;
|
||
|
|
size_t creditIdx_ = 0;
|
||
|
|
size_t creditChar_ = 0;
|
||
|
|
bool creditLineOpen_ = false;
|
||
|
|
bool creditsDone_ = false;
|
||
|
|
uint32_t creditLineAt_ = 0;
|
||
|
|
bool cursor_ = false;
|
||
|
|
bool creditsCursor_ = false;
|
||
|
|
};
|
||
|
|
|
||
|
|
} // namespace el512sa
|