mirror of
https://github.com/esphome/esphome.git
synced 2025-01-23 04:45:58 +01:00
Impl. "set text" action incl. "scroll left" effect
This commit is contained in:
parent
ef9f16a9dc
commit
3f07667a49
6 changed files with 350 additions and 196 deletions
|
@ -16,6 +16,32 @@ template<typename... Ts> class SetBrightnessAction : public Action<Ts...>, publi
|
|||
void play(Ts... x) override { this->parent_->set_brightness(this->brightness_.value(x...)); }
|
||||
};
|
||||
|
||||
|
||||
template<typename... Ts> class SetTextAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit SetTextAction(MAX6921Component *max9621) : max9621_(max9621) {}
|
||||
|
||||
TEMPLATABLE_VALUE(std::string, text)
|
||||
TEMPLATABLE_VALUE(uint8_t, text_position)
|
||||
TEMPLATABLE_VALUE(std::string, text_align)
|
||||
TEMPLATABLE_VALUE(std::string, text_effect)
|
||||
TEMPLATABLE_VALUE(uint8_t, text_effect_cycle_num)
|
||||
|
||||
void play(Ts... x) override {
|
||||
auto pos = this->text_position_.value(x...);
|
||||
auto cycle_num = this->text_effect_cycle_num_.value(x...);
|
||||
this->max9621_->display_->set_text(this->text_.value(x...),
|
||||
this->text_align_.value(x...),
|
||||
this->text_effect_.value(x...),
|
||||
pos,
|
||||
cycle_num);
|
||||
}
|
||||
|
||||
protected:
|
||||
MAX6921Component *max9621_;
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
template<typename... Ts> class SetDemoModeAction : public Action<Ts...>, public Parented<MAX6921Component> {
|
||||
public:
|
||||
|
@ -34,7 +60,7 @@ template<typename... Ts> class SetDemoModeAction : public Action<Ts...> {
|
|||
explicit SetDemoModeAction(MAX6921Component *max9621) : max9621_(max9621) {}
|
||||
|
||||
TEMPLATABLE_VALUE(std::string, mode)
|
||||
TEMPLATABLE_VALUE(uint8_t, cycle_num)
|
||||
TEMPLATABLE_VALUE(uint8_t, demo_cycle_num)
|
||||
|
||||
// overlay to cover string inputs
|
||||
// void set_mode(const std::string mode);
|
||||
|
@ -49,7 +75,7 @@ template<typename... Ts> class SetDemoModeAction : public Action<Ts...> {
|
|||
// }
|
||||
|
||||
void play(Ts... x) override {
|
||||
auto cycle_num = this->cycle_num_.value(x...);
|
||||
auto cycle_num = this->demo_cycle_num_.value(x...);
|
||||
this->max9621_->display_->set_demo_mode(this->mode_.value(x...), cycle_num);
|
||||
}
|
||||
|
||||
|
@ -60,13 +86,5 @@ template<typename... Ts> class SetDemoModeAction : public Action<Ts...> {
|
|||
};
|
||||
|
||||
|
||||
template<typename... Ts> class SetTextAction : public Action<Ts...>, public Parented<MAX6921Component> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(std::string, text)
|
||||
|
||||
void play(Ts... x) override { this->parent_->set_text(this->text_.value(x...)); }
|
||||
};
|
||||
|
||||
|
||||
} // namespace max9621
|
||||
} // namespace esphome
|
||||
|
|
|
@ -164,7 +164,7 @@ void Display::setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>&
|
|||
);
|
||||
|
||||
ESP_LOGCONFIG(TAG, "Display mode: %u", this->mode);
|
||||
ESP_LOGCONFIG(TAG, "Display scroll mode: %u", this->scroll_mode);
|
||||
ESP_LOGCONFIG(TAG, "Display scroll mode: %u", this->disp_text_.effect);
|
||||
}
|
||||
|
||||
void HOT Display::display_refresh_task_(void *pv) {
|
||||
|
@ -292,16 +292,19 @@ void Display::update(void) {
|
|||
this->brightness_cfg_changed_ = false;
|
||||
}
|
||||
|
||||
// handle display scroll modes...
|
||||
switch (this->scroll_mode) {
|
||||
case DISP_SCROLL_MODE_LEFT:
|
||||
update_out_buf_(this->disp_text_);
|
||||
scroll_left_(this->disp_text_);
|
||||
break;
|
||||
case DISP_SCROLL_MODE_OFF:
|
||||
default:
|
||||
this->mode = DISP_MODE_PRINT;
|
||||
break;
|
||||
// handle text effects...
|
||||
if (this->disp_text_.effect != TEXT_EFFECT_NONE) { // any effect enabled?
|
||||
switch (this->disp_text_.effect) {
|
||||
case TEXT_EFFECT_SCROLL_LEFT:
|
||||
update_out_buf_();
|
||||
this->disp_text_.scroll_left();
|
||||
break;
|
||||
default:
|
||||
set_mode(DISP_MODE_PRINT);
|
||||
break;
|
||||
}
|
||||
if (this->disp_text_.effect == TEXT_EFFECT_NONE) // effect finished?
|
||||
set_mode(DISP_MODE_PRINT); // yes -> switch back to "it" interface
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +329,7 @@ void Display::set_demo_mode(demo_mode_t mode, uint8_t cycle_num) {
|
|||
this->disp_text_.text[text_idx] = 0;
|
||||
ESP_LOGV(TAG, "%s(): text: %s", __func__, this->disp_text_.text);
|
||||
|
||||
set_scroll_mode(&this->disp_text_, DISP_SCROLL_MODE_LEFT, cycle_num);
|
||||
this->disp_text_.set_text_effect(TEXT_EFFECT_SCROLL_LEFT, cycle_num);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -346,48 +349,68 @@ void Display::set_demo_mode(const std::string& mode, uint8_t cycle_num) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Shows the given text on the display at given position.
|
||||
* @brief Triggered by action. Shows the given text on the display.
|
||||
*
|
||||
* @param start_pos display position 0..n
|
||||
* @param str text to display
|
||||
* @param text text to display
|
||||
* @param align text alignment
|
||||
* @param effect text effect
|
||||
* @param start_pos display position 0..n (optional, default=0)
|
||||
* @param cycle_num text effect cycle count (optional, default=endless)
|
||||
*
|
||||
* @return number of characters displayed
|
||||
*/
|
||||
int Display::set_text(uint8_t start_pos, const char *str) {
|
||||
ESP_LOGVV(TAG, "%s(): str=%s, prev=%s", __func__, str, this->disp_text_.text);
|
||||
if (strncmp(str, this->disp_text_.text, sizeof(this->disp_text_.text)) == 0) // text not changed?
|
||||
// if (strncmp(str, &this->disp_text_.text[this->disp_text_.visible_idx],
|
||||
// this->disp_text_.visible_len) == 0) // text not changed?
|
||||
return strlen(str); // yes -> exit function
|
||||
ESP_LOGV(TAG, "%s(): text changed: str=%s, prev=%s", __func__, str, this->disp_text_.text);
|
||||
int Display::set_text(const std::string& text, const std::string& align,
|
||||
const std::string& effect, uint8_t start_pos, uint8_t cycle_num) {
|
||||
ESP_LOGD(TAG, "set text (given): text=%s, start-pos=%u, align=%s, effect=%s, cycle-num=%u",
|
||||
text.c_str(), start_pos, align.c_str(), effect.c_str(), cycle_num);
|
||||
|
||||
// store new text...
|
||||
this->disp_text_.set(start_pos, this->num_digits_ - 1, str);
|
||||
this->disp_text_.set_text(start_pos, this->num_digits_ - 1, text);
|
||||
|
||||
// update visible text...
|
||||
this->disp_text_.visible_idx = 0;
|
||||
switch (this->scroll_mode) {
|
||||
case DISP_SCROLL_MODE_LEFT:
|
||||
this->disp_text_.visible_len = 1;
|
||||
break;
|
||||
case DISP_SCROLL_MODE_OFF:
|
||||
default:
|
||||
this->disp_text_.visible_len = std::min(strlen(this->disp_text_.text), this->num_digits_-start_pos);
|
||||
break;
|
||||
}
|
||||
// set text align...
|
||||
this->disp_text_.set_text_align(align);
|
||||
|
||||
return update_out_buf_(this->disp_text_);
|
||||
// set text effect...
|
||||
this->disp_text_.set_text_effect(effect, cycle_num);
|
||||
|
||||
// update display mode...
|
||||
set_mode(DISP_MODE_OTHER);
|
||||
|
||||
ESP_LOGD(TAG, "set text (result): text=%s, start-pos=%u, vi-idx=%u, vi-len=%u",
|
||||
this->disp_text_.text, this->disp_text_.start_pos,
|
||||
this->disp_text_.visible_idx, this->disp_text_.visible_len);
|
||||
|
||||
return update_out_buf_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Triggered by it.print(). Shows the given text on the display.
|
||||
*
|
||||
* @param text text to display
|
||||
* @param start_pos display position 0..n (optional, default=0)
|
||||
*
|
||||
* @return number of characters displayed
|
||||
*/
|
||||
int Display::set_text(const char *text, uint8_t start_pos) {
|
||||
ESP_LOGVV(TAG, "%s(): str=%s, prev=%s", __func__, text, this->disp_text_.text);
|
||||
if (strncmp(text, this->disp_text_.text, sizeof(this->disp_text_.text)) == 0) // text not changed?
|
||||
return strlen(text); // yes -> exit function
|
||||
ESP_LOGV(TAG, "%s(): text changed: str=%s, prev=%s", __func__, text, this->disp_text_.text);
|
||||
|
||||
// store new text...
|
||||
std::string text_str = text;
|
||||
this->disp_text_.set_text(start_pos, this->num_digits_ - 1, text_str);
|
||||
|
||||
return update_out_buf_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the display buffer containing the MAX6921 OUT data according
|
||||
* to current visible text.
|
||||
*
|
||||
* @param text display text object
|
||||
|
||||
* @return number of visible characters
|
||||
*/
|
||||
int Display::update_out_buf_(DisplayText& disp_text) {
|
||||
int Display::update_out_buf_(void) {
|
||||
uint visible_idx_offset = 0;
|
||||
|
||||
for (uint pos=0; pos<this->num_digits_; pos++) {
|
||||
|
@ -396,21 +419,21 @@ int Display::update_out_buf_(DisplayText& disp_text) {
|
|||
bool bGetNextChar, bClearPos = true;
|
||||
do {
|
||||
// determine character for current display position...
|
||||
if ((pos < disp_text.start_pos) || // empty position before text or
|
||||
((disp_text.start_pos == 0) && (pos >= disp_text.visible_len))) // empty positions after text?
|
||||
if ((pos < this->disp_text_.start_pos) || // empty position before text or
|
||||
(pos >= (this->disp_text_.start_pos + this->disp_text_.visible_len))) // empty position after text?
|
||||
pos_char = ' ';
|
||||
else
|
||||
pos_char = disp_text.text[disp_text.visible_idx + visible_idx_offset++];
|
||||
pos_char = this->disp_text_.text[this->disp_text_.visible_idx + visible_idx_offset++];
|
||||
|
||||
// special handling for point segment...
|
||||
bGetNextChar = false;
|
||||
if (isPointSegOnly(pos_char)) { // is point segment only?
|
||||
if (disp_text.visible_idx+visible_idx_offset-1 > 0) { // not the 1st text character?
|
||||
if (isPointSegOnly(disp_text.text[disp_text.visible_idx + visible_idx_offset - 2])) { // previous text character wasn't a point?
|
||||
if (pos == 0) { // 1st (most left) display position?
|
||||
bGetNextChar = true; // yes -> ignore point, get next character
|
||||
if (isPointSegOnly(pos_char)) { // is point segment only?
|
||||
if (this->disp_text_.visible_idx+visible_idx_offset-1 > 0) { // not the 1st text character?
|
||||
if (isPointSegOnly(this->disp_text_.text[this->disp_text_.visible_idx + visible_idx_offset - 2])) { // previous text character wasn't a point?
|
||||
if (pos == 0) { // 1st (most left) display position?
|
||||
bGetNextChar = true; // yes -> ignore point, get next character
|
||||
} else {
|
||||
--pos; // no -> add point to previous display position
|
||||
--pos; // no -> add point to previous display position
|
||||
bClearPos = false;
|
||||
}
|
||||
}
|
||||
|
@ -425,7 +448,7 @@ int Display::update_out_buf_(DisplayText& disp_text) {
|
|||
((pos_char - ' ') < ARRAY_ELEM_COUNT(ASCII_TO_SEG))) { // supported char?
|
||||
out_data = this->ascii_out_data_[pos_char - ' ']; // yes ->
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Encountered unsupported character '%c (0x%02x)'!", pos_char, pos_char);
|
||||
ESP_LOGW(TAG, "Encountered unsupported character (0x%02x): %c", pos_char, (pos_char>=0x20)?pos_char:' ');
|
||||
out_data = SEG_UNSUPPORTED_CHAR;
|
||||
}
|
||||
ESP_LOGVV(TAG, "%s(): segment data: 0x%06x", __func__, out_data);
|
||||
|
@ -456,90 +479,12 @@ int Display::update_out_buf_(DisplayText& disp_text) {
|
|||
this->out_buf_[pos*3+2]);
|
||||
|
||||
ESP_LOGV(TAG, "%s(): pos=%u, char='%c' (0x%02x), vi-idx=%u, vi-idx-off=%u, vi-len=%u",
|
||||
__func__, pos, pos_char, pos_char, disp_text.visible_idx, visible_idx_offset, disp_text.visible_len);
|
||||
__func__, pos, pos_char, pos_char, this->disp_text_.visible_idx, visible_idx_offset, this->disp_text_.visible_len);
|
||||
}
|
||||
|
||||
disp_text.content_changed = true;
|
||||
this->disp_text_.content_changed = true;
|
||||
|
||||
return this->num_digits_ - disp_text.start_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*/
|
||||
DisplayScrollMode::DisplayScrollMode() {
|
||||
this->scroll_mode = DISP_SCROLL_MODE_OFF;
|
||||
this->disp_text_ = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inits the text object according to scroll mode.
|
||||
*/
|
||||
void DisplayScrollMode::init_scroll_mode_(void) {
|
||||
switch (this->scroll_mode) {
|
||||
case DISP_SCROLL_MODE_LEFT:
|
||||
this->disp_text_->start_pos = this->disp_text_->max_pos; // start at right side
|
||||
this->disp_text_->visible_idx = 0;
|
||||
this->disp_text_->visible_len = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the scroll mode.
|
||||
*
|
||||
* @param disp_text display text object
|
||||
* @param mode scroll mode
|
||||
* @param cycle_num number of scroll cycles (optional, default=endless)
|
||||
*/
|
||||
void DisplayScrollMode::set_scroll_mode(DisplayText *disp_text, display_scroll_mode_t mode, uint8_t cycle_num)
|
||||
{
|
||||
if (!disp_text) {
|
||||
ESP_LOGE(TAG, "Invalid display text object");
|
||||
return;
|
||||
}
|
||||
if (mode >= DISP_SCROLL_MODE_LAST_ENUM) {
|
||||
ESP_LOGE(TAG, "Invalid display scroll mode: %i", mode);
|
||||
return;
|
||||
}
|
||||
this->disp_text_ = disp_text;
|
||||
this->scroll_mode = mode;
|
||||
this->cycle_num = cycle_num;
|
||||
init_scroll_mode_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the mode "scroll left".
|
||||
*
|
||||
* @param text display text object
|
||||
*/
|
||||
void DisplayScrollMode::scroll_left_(DisplayText& disp_text) {
|
||||
ESP_LOGV(TAG, "%s(): ENTRY: start-idx=%u, text-idx=%u, text-len=%u", __func__,
|
||||
disp_text.start_pos, disp_text.visible_idx, disp_text.visible_len);
|
||||
|
||||
// update visible text...
|
||||
if (disp_text.start_pos > 0) { // no start at left side of display (scroll in from right side)?
|
||||
--disp_text.start_pos; // decrement display start position
|
||||
++disp_text.visible_len; // increment visible text length
|
||||
} else {
|
||||
++disp_text.visible_idx; // increment visible start index
|
||||
if ((disp_text.visible_idx + disp_text.visible_len) >= strlen(disp_text.text)) // visible part reached at end of text?
|
||||
--disp_text.visible_len; // decrement visible text length (scroll out to left side)
|
||||
}
|
||||
|
||||
// update scroll mode...
|
||||
if (disp_text.visible_len == 0) {
|
||||
init_scroll_mode_();
|
||||
if (this->cycle_num > 0) {
|
||||
if (--this->cycle_num == 0) {
|
||||
this->scroll_mode = DISP_SCROLL_MODE_OFF;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s(): EXIT: start-idx=%u, text-idx=%u, text-len=%u", __func__,
|
||||
disp_text.start_pos, disp_text.visible_idx, disp_text.visible_len);
|
||||
return this->num_digits_ - this->disp_text_.start_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -552,18 +497,20 @@ DisplayText::DisplayText() {
|
|||
this->content_changed = false;
|
||||
this->start_pos = 0;
|
||||
this->max_pos = 0;
|
||||
this->align = TEXT_ALIGN_CENTER;
|
||||
this->effect = TEXT_EFFECT_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stores the given text.
|
||||
*
|
||||
* @param start_pos display start position (0..n)
|
||||
* @param max_pos display max. position
|
||||
* @param str text to store
|
||||
* @param start_pos display start position of text (0..n)
|
||||
* @param max_pos display max. position (as index)
|
||||
* @param text text to store
|
||||
*
|
||||
* @return number of stored characters
|
||||
*/
|
||||
int DisplayText::set(uint start_pos, uint max_pos, const char *str) {
|
||||
int DisplayText::set_text(uint start_pos, uint max_pos, const std::string& text) {
|
||||
// check start position...
|
||||
if (start_pos >= max_pos) {
|
||||
ESP_LOGW(TAG, "Invalid start position: %u");
|
||||
|
@ -571,13 +518,182 @@ int DisplayText::set(uint start_pos, uint max_pos, const char *str) {
|
|||
}
|
||||
else
|
||||
this->start_pos = start_pos;
|
||||
this->max_pos = max_pos;
|
||||
|
||||
strncpy(this->text, str, sizeof(this->text) - 1);
|
||||
this->max_pos = max_pos;
|
||||
strncpy(this->text, text.c_str(), sizeof(this->text) - 1);
|
||||
this->text[sizeof(this->text)-1] = 0;
|
||||
this->visible_idx = 0;
|
||||
this->visible_len = std::min(strlen(this->text), this->max_pos - this->start_pos + 1);
|
||||
return strlen(this->text);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Inits the text object according to selected align.
|
||||
*/
|
||||
void DisplayText::init_text_align_(void) {
|
||||
this->visible_idx = 0;
|
||||
this->visible_len = std::min(strlen(this->text), this->max_pos + 1);
|
||||
switch (this->align) {
|
||||
case TEXT_ALIGN_LEFT:
|
||||
this->start_pos = 0;
|
||||
break;
|
||||
case TEXT_ALIGN_CENTER:
|
||||
this->start_pos = ((this->max_pos+1) - this->visible_len) / 2;
|
||||
break;
|
||||
case TEXT_ALIGN_RIGHT:
|
||||
this->start_pos = (this->max_pos+1) - this->visible_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inits the text object according to selected effect.
|
||||
*/
|
||||
void DisplayText::init_text_effect_(void) {
|
||||
switch (this->effect) {
|
||||
case TEXT_EFFECT_SCROLL_LEFT:
|
||||
this->start_pos = this->max_pos; // start at right side
|
||||
this->visible_idx = 0;
|
||||
this->visible_len = 1;
|
||||
break;
|
||||
case TEXT_EFFECT_NONE:
|
||||
case TEXT_EFFECT_BLINK:
|
||||
default:
|
||||
// Don't change display start position!
|
||||
this->visible_idx = 0;
|
||||
this->visible_len = std::min(strlen(this->text), this->max_pos - this->start_pos + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the text align.
|
||||
*
|
||||
* @param align text align
|
||||
*/
|
||||
void DisplayText::set_text_align(text_align_t align)
|
||||
{
|
||||
if (align >= TEXT_ALIGN_LAST_ENUM) {
|
||||
ESP_LOGE(TAG, "Invalid display text align: %i", align);
|
||||
return;
|
||||
}
|
||||
this->align = align;
|
||||
init_text_align_();
|
||||
ESP_LOGD(TAG, "set align: text=%s, align=%i, start-pos=%u, max-pos=%u, vi-idx=%u, vi-len=%u",
|
||||
this->text, this->align, this->start_pos, this->max_pos, this->visible_idx, this->visible_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the text align.
|
||||
*
|
||||
* @param align text align (as string)
|
||||
*/
|
||||
void DisplayText::set_text_align(const std::string& align)
|
||||
{
|
||||
text_align_t text_align = TEXT_ALIGN_LAST_ENUM;
|
||||
|
||||
if (!align.empty()) {
|
||||
if (str_equals_case_insensitive(align, "left"))
|
||||
text_align = TEXT_ALIGN_LEFT;
|
||||
else if (str_equals_case_insensitive(align, "center"))
|
||||
text_align = TEXT_ALIGN_CENTER;
|
||||
else if (str_equals_case_insensitive(align, "right"))
|
||||
text_align = TEXT_ALIGN_RIGHT;
|
||||
else
|
||||
ESP_LOGW(TAG, "Invalid text align: %s", align);
|
||||
}
|
||||
else
|
||||
ESP_LOGW(TAG, "No text align given");
|
||||
if (text_align >= TEXT_ALIGN_LAST_ENUM)
|
||||
return;
|
||||
set_text_align(text_align);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the text effect.
|
||||
*
|
||||
* @param effect text effect
|
||||
* @param cycle_num number of effect cycles (optional, default=endless)
|
||||
*/
|
||||
void DisplayText::set_text_effect(text_effect_t effect, uint8_t cycle_num)
|
||||
{
|
||||
if (effect >= TEXT_EFFECT_LAST_ENUM) {
|
||||
ESP_LOGE(TAG, "Invalid display text effect: %i", effect);
|
||||
return;
|
||||
}
|
||||
if (effect != this->effect) {
|
||||
this->effect = effect;
|
||||
this->cycle_num = cycle_num;
|
||||
init_text_effect_();
|
||||
ESP_LOGD(TAG, "set effect: text=%s, effect=%i, cycles=%u, start-pos=%u, max-pos=%u, vi-idx=%u, vi-len=%u",
|
||||
this->text, this->effect, this->cycle_num, this->start_pos,
|
||||
this->max_pos, this->visible_idx, this->visible_len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the text effect.
|
||||
*
|
||||
* @param effect text effect (as string)
|
||||
* @param cycle_num number of effect cycles (optional, default=endless)
|
||||
*/
|
||||
void DisplayText::set_text_effect(const std::string& effect, uint8_t cycle_num)
|
||||
{
|
||||
text_effect_t text_effect = TEXT_EFFECT_LAST_ENUM;
|
||||
|
||||
if (!effect.empty()) {
|
||||
if (str_equals_case_insensitive(effect, "none"))
|
||||
text_effect = TEXT_EFFECT_NONE;
|
||||
else if (str_equals_case_insensitive(effect, "blink"))
|
||||
text_effect = TEXT_EFFECT_BLINK;
|
||||
else if (str_equals_case_insensitive(effect, "scroll_left"))
|
||||
text_effect = TEXT_EFFECT_SCROLL_LEFT;
|
||||
else
|
||||
ESP_LOGW(TAG, "Invalid text effect: %s", effect);
|
||||
}
|
||||
else
|
||||
ESP_LOGW(TAG, "No text effect given");
|
||||
if (text_effect >= TEXT_EFFECT_LAST_ENUM)
|
||||
return;
|
||||
set_text_effect(text_effect, cycle_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the mode "scroll left".
|
||||
*/
|
||||
void DisplayText::scroll_left(void) {
|
||||
ESP_LOGV(TAG, "%s(): ENTRY: start-idx=%u, text-idx=%u, text-len=%u", __func__,
|
||||
this->start_pos, this->visible_idx, this->visible_len);
|
||||
|
||||
// update visible text...
|
||||
if (this->start_pos > 0) { // left display side not reached (scroll in from right side)?
|
||||
--this->start_pos; // decrement display start position
|
||||
if (this->visible_len < strlen(this->text))
|
||||
++this->visible_len; // increment visible text length
|
||||
} else {
|
||||
++this->visible_idx; // increment visible start index
|
||||
if ((this->visible_idx + this->visible_len) > strlen(this->text)) // visible part reached at end of text?
|
||||
--this->visible_len; // decrement visible text length (scroll out to left side)
|
||||
}
|
||||
|
||||
// update effect mode...
|
||||
if (this->visible_len == 0) {
|
||||
init_text_effect_();
|
||||
if (this->cycle_num > 0) {
|
||||
ESP_LOGD(TAG, "scroll cycle finished (%u left)", this->cycle_num-1);
|
||||
if (--this->cycle_num == 0) {
|
||||
this->effect = TEXT_EFFECT_NONE;
|
||||
ESP_LOGD(TAG, "scroll finished");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s(): EXIT: start-idx=%u, text-idx=%u, text-len=%u", __func__,
|
||||
this->start_pos, this->visible_idx, this->visible_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the PWM for display brightness control.
|
||||
*
|
||||
|
@ -595,7 +711,7 @@ uint32_t DisplayBrightness::config_brightness_pwm(uint8_t pwm_pin_no, uint8_t ch
|
|||
if ((freq_supported = ledcSetup(channel, freq, resolution)) != 0) {
|
||||
ledcAttachPin(pwm_pin_no, channel);
|
||||
this->brightness_pwm_channel_ = channel;
|
||||
this->brightness_max_duty_ = pow(2,resolution); // max. duty value for given resolution
|
||||
this->brightness_max_duty_ = pow(2,resolution); // max. duty value for given resolution
|
||||
ESP_LOGD(TAG, "Prepare brightness PWM: pin=%u, channel=%u, resolution=%ubit, freq=%uHz",
|
||||
pwm_pin_no, channel, resolution, freq_supported);
|
||||
} else {
|
||||
|
@ -630,8 +746,10 @@ void DisplayMode::set_mode(display_mode_t display_mode) {
|
|||
ESP_LOGE(TAG, "Invalid display mode: %i", display_mode);
|
||||
return;
|
||||
}
|
||||
this->mode = display_mode;
|
||||
ESP_LOGD(TAG, "Set display mode: %i", this->mode);
|
||||
if (display_mode != this->mode) {
|
||||
this->mode = display_mode;
|
||||
ESP_LOGD(TAG, "Set display mode: %i", this->mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,10 +19,19 @@ enum display_mode_t {
|
|||
DISP_MODE_LAST_ENUM
|
||||
};
|
||||
|
||||
enum display_scroll_mode_t {
|
||||
DISP_SCROLL_MODE_OFF, // show text at given position, cut if too long
|
||||
DISP_SCROLL_MODE_LEFT, // scroll left, start with 1st char at right position
|
||||
DISP_SCROLL_MODE_LAST_ENUM
|
||||
enum text_align_t {
|
||||
TEXT_ALIGN_LEFT,
|
||||
TEXT_ALIGN_CENTER,
|
||||
TEXT_ALIGN_RIGHT,
|
||||
TEXT_ALIGN_LAST_ENUM
|
||||
};
|
||||
|
||||
enum text_effect_t {
|
||||
TEXT_EFFECT_NONE, // show text at given position, cut if too long
|
||||
TEXT_EFFECT_BLINK, // blink
|
||||
TEXT_EFFECT_SCROLL_LEFT, // scroll left, start with 1st char at right position
|
||||
// TEXT_EFFECT_SCROLL_RIGHT, // scroll right, start with last char at left position
|
||||
TEXT_EFFECT_LAST_ENUM
|
||||
};
|
||||
|
||||
enum demo_mode_t {
|
||||
|
@ -45,6 +54,17 @@ class DisplayBrightness
|
|||
uint8_t brightness_pwm_channel_;
|
||||
};
|
||||
|
||||
class DisplayMode
|
||||
{
|
||||
public:
|
||||
display_mode_t mode;
|
||||
DisplayMode();
|
||||
void set_mode(display_mode_t display_mode);
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
class DisplayText
|
||||
{
|
||||
public:
|
||||
|
@ -54,38 +74,24 @@ class DisplayText
|
|||
char text[DISPLAY_TEXT_LEN + 1]; // current text to display (may be larger then display)
|
||||
uint visible_idx; // current index of start of visible part
|
||||
uint visible_len; // current length of visible text
|
||||
DisplayText();
|
||||
int set(uint start_pos, uint max_pos, const char *str);
|
||||
};
|
||||
|
||||
class DisplayMode
|
||||
{
|
||||
public:
|
||||
display_mode_t mode; // display mode
|
||||
DisplayMode();
|
||||
void set_mode(display_mode_t display_mode);
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
class DisplayScrollMode
|
||||
{
|
||||
public:
|
||||
display_scroll_mode_t scroll_mode; // scroll mode
|
||||
text_align_t align;
|
||||
text_effect_t effect;
|
||||
uint8_t cycle_num;
|
||||
DisplayScrollMode();
|
||||
void set_scroll_mode(DisplayText *disp_text, display_scroll_mode_t scroll_mode, uint8_t cycle_num=0);
|
||||
DisplayText();
|
||||
void scroll_left(void);
|
||||
int set_text(uint start_pos, uint max_pos, const std::string& text);
|
||||
void set_text_align(text_align_t align);
|
||||
void set_text_align(const std::string& align);
|
||||
void set_text_effect(text_effect_t effect, uint8_t cycle_num=0);
|
||||
void set_text_effect(const std::string& effect, uint8_t cycle_num=0);
|
||||
|
||||
protected:
|
||||
DisplayText *disp_text_;
|
||||
void init_scroll_mode_(void);
|
||||
void scroll_left_(DisplayText& disp_text);
|
||||
void init_text_align_(void);
|
||||
void init_text_effect_(void);
|
||||
};
|
||||
|
||||
class Display : public DisplayBrightness,
|
||||
public DisplayMode,
|
||||
public DisplayScrollMode
|
||||
public DisplayMode
|
||||
{
|
||||
public:
|
||||
Display(MAX6921Component *max6921) { max6921_ = max6921; }
|
||||
|
@ -95,7 +101,9 @@ class Display : public DisplayBrightness,
|
|||
void setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>& pos_to_out_map);
|
||||
void set_demo_mode(demo_mode_t mode, uint8_t cycle_num);
|
||||
void set_demo_mode(const std::string& mode, uint8_t cycle_num);
|
||||
int set_text(uint8_t start_pos, const char *str);
|
||||
int set_text(const char *text, uint8_t start_pos);
|
||||
int set_text(const std::string& text, const std::string& align, const std::string& effect,
|
||||
uint8_t start_pos=0, uint8_t cycle_num=0);
|
||||
void update(void);
|
||||
|
||||
protected:
|
||||
|
@ -110,7 +118,7 @@ class Display : public DisplayBrightness,
|
|||
uint32_t refresh_period_us_;
|
||||
DisplayText disp_text_;
|
||||
static void display_refresh_task_(void *pv);
|
||||
int update_out_buf_(DisplayText& disp_text);
|
||||
int update_out_buf_(void);
|
||||
|
||||
private:
|
||||
void init_font__(void);
|
||||
|
|
|
@ -7,7 +7,8 @@ from esphome.const import (
|
|||
CONF_BRIGHTNESS,
|
||||
CONF_LAMBDA,
|
||||
CONF_MODE,
|
||||
# CONF_POSITION,
|
||||
CONF_POSITION,
|
||||
CONF_EFFECT,
|
||||
)
|
||||
|
||||
|
||||
|
@ -42,6 +43,7 @@ CONF_POS_12_PIN = "pos_12_pin"
|
|||
# CONF_DEMO_MODE = "demo_mode"
|
||||
CONF_CYCLE_NUM = "cycle_num"
|
||||
CONF_TEXT = "text"
|
||||
CONF_ALIGN = "align"
|
||||
|
||||
|
||||
max6921_ns = cg.esphome_ns.namespace("max6921")
|
||||
|
@ -204,7 +206,6 @@ async def max6921_set_brightness_to_code(config, action_id, template_arg, args):
|
|||
return var
|
||||
|
||||
|
||||
"""
|
||||
def validate_action_set_text(value):
|
||||
print(f"validate_action_set_text: {value}")
|
||||
return value
|
||||
|
@ -216,7 +217,12 @@ ACTION_SET_TEXT_SCHEMA = cv.All(
|
|||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_TEXT): cv.templatable(cv.string),
|
||||
cv.Optional(CONF_POSITION): cv.templatable(cv.int_range(min=0, max=13))
|
||||
cv.Optional(CONF_POSITION): cv.templatable(
|
||||
cv.int_range(min=0, max=13)
|
||||
),
|
||||
cv.Optional(CONF_ALIGN): cv.templatable(cv.string),
|
||||
cv.Optional(CONF_EFFECT): cv.templatable(cv.string),
|
||||
cv.Optional(CONF_CYCLE_NUM, default=0): cv.templatable(cv.uint8_t),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
@ -225,16 +231,25 @@ ACTION_SET_TEXT_SCHEMA = cv.All(
|
|||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"max6921.set_text", SetTextAction, ACTION_SET_TEXT_SCHEMA
|
||||
)
|
||||
@automation.register_action("max6921.set_text", SetTextAction, ACTION_SET_TEXT_SCHEMA)
|
||||
async def max6921_set_text_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = await cg.templatable(config[CONF_TEXT], args, cg.std_string)
|
||||
cg.add(var.set_text(template_))
|
||||
if CONF_POSITION in config:
|
||||
template_ = await cg.templatable(config[CONF_POSITION], args, cg.uint8)
|
||||
cg.add(var.set_text_position(template_))
|
||||
if CONF_ALIGN in config:
|
||||
template_ = await cg.templatable(config[CONF_ALIGN], args, cg.std_string)
|
||||
cg.add(var.set_text_align(template_))
|
||||
if CONF_EFFECT in config:
|
||||
template_ = await cg.templatable(config[CONF_EFFECT], args, cg.std_string)
|
||||
cg.add(var.set_text_effect(template_))
|
||||
if CONF_CYCLE_NUM in config:
|
||||
template_ = await cg.templatable(config[CONF_CYCLE_NUM], args, cg.uint8)
|
||||
cg.add(var.set_text_effect_cycle_num(template_))
|
||||
return var
|
||||
"""
|
||||
|
||||
|
||||
ACTION_SET_DEMO_MODE_SCHEMA = cv.All(
|
||||
|
@ -263,5 +278,5 @@ async def max6921_set_demo_mode_to_code(config, action_id, template_arg, args):
|
|||
cg.add(var.set_mode(template_))
|
||||
if CONF_CYCLE_NUM in config:
|
||||
template_ = await cg.templatable(config[CONF_CYCLE_NUM], args, cg.uint8)
|
||||
cg.add(var.set_cycle_num(template_))
|
||||
cg.add(var.set_demo_cycle_num(template_))
|
||||
return var
|
||||
|
|
|
@ -59,10 +59,6 @@ void MAX6921Component::set_brightness(float brightness) {
|
|||
}
|
||||
}
|
||||
|
||||
void MAX6921Component::set_text(const std::string& text) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clocks data into MAX6921 via SPI (MSB first).
|
||||
* Data must contain 3 bytes with following format:
|
||||
|
@ -100,7 +96,7 @@ void MAX6921Component::update() {
|
|||
uint8_t MAX6921Component::print(uint8_t start_pos, const char *str) {
|
||||
if (this->display_->mode != DISP_MODE_PRINT) // not in "it.print" mode?
|
||||
return strlen(str); // yes -> abort
|
||||
return this->display_->set_text(start_pos, str);
|
||||
return this->display_->set_text(str, start_pos);
|
||||
}
|
||||
|
||||
uint8_t MAX6921Component::print(const char *str) { return this->print(0, str); }
|
||||
|
|
|
@ -32,7 +32,6 @@ class MAX6921Component : public PollingComponent,
|
|||
void set_load_pin(GPIOPin *load) { this->load_pin_ = load; }
|
||||
void set_seg_to_out_pin_map(const std::vector<uint8_t> &pin_map) { this->seg_to_out_map__ = pin_map; }
|
||||
void set_pos_to_out_pin_map(const std::vector<uint8_t> &pin_map) { this->pos_to_out_map__ = pin_map; }
|
||||
void set_text(const std::string& text);
|
||||
void set_writer(max6921_writer_t &&writer);
|
||||
void setup() override;
|
||||
uint8_t strftime(uint8_t pos, const char *format, ESPTime time) __attribute__((format(strftime, 3, 0)));
|
||||
|
|
Loading…
Reference in a new issue