Public Access
Add ESPHome display component; ring-buffer driver shared with PlatformIO
Driver (components/el512/el512_panel.*, ESP-IDF only): - DMA ring of 8 x 4 lines (17 KB) refilled from the I2S EOF interrupt (IRAM) instead of a 142 KB full-frame stream; ~107 KB heap freed. - 256-entry lookup table encodes 8 pixels per step. - Back buffer + displayed buffer, swapped at the start of a frame. - PlatformIO builds it via lib_extra_dirs (EL512Core); lib/EL512 keeps the Adafruit GFX front end. ESPHome external component (platform: el512): - DisplayBuffer with optional ENABLE / _LOWPWR pins, set_enabled(), set_low_power(), helper functions for page lambdas. - still_alive_page: plays the Portal end-credits show, then returns to the previous page. Still Alive engine moved to components/el512/still_alive.* with a built-in 5x7 font (from Adafruit GFX, BSD); the PlatformIO demo uses the same code. The importer writes components/el512/still_alive_data.h and stops at 200 s (--until-ms), matching the hand-trimmed data. esphome/el512-panel.yaml: 8 pages (clock, forecast, agenda, dashboard, now playing, Plex, solar, Still Alive), page select, rotation, display and low-power switches, message text. home_assistant/packages/el512_panel.yaml: helper template sensors for forecast, agenda, now playing and Plex streams. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
410885de24
commit
963590cdfe
27 files changed
+2110
-828
No files matched your search
@@ -0,0 +1,110 @@
|
||||
// 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
|
||||
Reference in new issue
Block a user