mirror of
https://github.com/esphome/esphome.git
synced 2024-12-02 19:54:14 +01:00
[max6921] Add options "repeat_num" and "repeat_interval" to "set_text" action
With these options a defined effect (e.g. blink 3 times) can be repeated x times or endless.
This commit is contained in:
parent
36c5e829d6
commit
4f8f38ce40
4 changed files with 324 additions and 124 deletions
|
@ -28,15 +28,20 @@ template<typename... Ts> class SetTextAction : public Action<Ts...> {
|
|||
TEMPLATABLE_VALUE(std::string, text_effect)
|
||||
TEMPLATABLE_VALUE(uint8_t, text_effect_cycle_num)
|
||||
TEMPLATABLE_VALUE(uint32_t, text_effect_duration)
|
||||
TEMPLATABLE_VALUE(uint8_t, text_repeat_num)
|
||||
TEMPLATABLE_VALUE(uint32_t, text_repeat_interval)
|
||||
TEMPLATABLE_VALUE(uint32_t, text_effect_update_interval)
|
||||
|
||||
void play(Ts... x) override {
|
||||
auto pos = this->text_position_.value(x...);
|
||||
auto cycle_num = this->text_effect_cycle_num_.value(x...);
|
||||
auto effect_cycle_num = this->text_effect_cycle_num_.value(x...);
|
||||
auto duration = this->text_effect_duration_.value(x...);
|
||||
auto repeat_num = this->text_repeat_num_.value(x...);
|
||||
auto repeat_interval = this->text_repeat_interval_.value(x...);
|
||||
auto update_interval = this->text_effect_update_interval_.value(x...);
|
||||
this->max9621_->display_->set_text(this->text_.value(x...), pos, this->text_align_.value(x...), duration,
|
||||
this->text_effect_.value(x...), update_interval, cycle_num);
|
||||
this->text_effect_.value(x...), effect_cycle_num, repeat_num, repeat_interval,
|
||||
update_interval);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -277,10 +277,12 @@ void Display::clear(int pos) {
|
|||
* @param interval_ms update interval in ms (optional, default=restore)
|
||||
*/
|
||||
void Display::set_update_interval(uint32_t interval_ms) {
|
||||
ESP_LOGD(TAG, "Change polling interval: %" PRIu32 "ms", interval_ms);
|
||||
this->max6921_->stop_poller();
|
||||
this->max6921_->set_update_interval(interval_ms);
|
||||
this->max6921_->start_poller();
|
||||
if ((interval_ms > 0) && (this->max6921_->get_update_interval() != interval_ms)) {
|
||||
ESP_LOGD(TAG, "Change polling interval: %" PRIu32 "ms", interval_ms);
|
||||
this->max6921_->stop_poller();
|
||||
this->max6921_->set_update_interval(interval_ms);
|
||||
this->max6921_->start_poller();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -311,39 +313,47 @@ void Display::update() {
|
|||
}
|
||||
|
||||
// handle text effects...
|
||||
if (this->disp_text_.effect != TEXT_EFFECT_NONE) { // any effect enabled?
|
||||
if ((this->mode != DISP_MODE_PRINT) && (this->disp_text_.effect != TEXT_EFFECT_NONE)) { // any effect enabled?
|
||||
switch (this->disp_text_.effect) {
|
||||
case TEXT_EFFECT_BLINK:
|
||||
update_out_buf_();
|
||||
this->disp_text_.blink();
|
||||
if (this->disp_text_.blink())
|
||||
set_mode(DISP_MODE_PRINT);
|
||||
break;
|
||||
case TEXT_EFFECT_SCROLL_LEFT:
|
||||
update_out_buf_();
|
||||
this->disp_text_.scroll_left();
|
||||
if (this->disp_text_.scroll_left())
|
||||
set_mode(DISP_MODE_PRINT);
|
||||
break;
|
||||
default:
|
||||
set_mode(DISP_MODE_PRINT);
|
||||
break;
|
||||
}
|
||||
if (this->disp_text_.effect == TEXT_EFFECT_NONE) { // effect finished?
|
||||
this->duration_ms = 0;
|
||||
restore_update_interval();
|
||||
set_mode(DISP_MODE_PRINT); // switch back to "it" interface
|
||||
}
|
||||
}
|
||||
|
||||
// handle duration...
|
||||
if (this->duration_ms > 0) {
|
||||
if ((millis() - this->duration_ms_start_) >= this->duration_ms) {
|
||||
ESP_LOGD(TAG, "Effect duration of %" PRIu32 "ms expired", this->duration_ms);
|
||||
this->disp_text_.set_text_effect(TEXT_EFFECT_NONE);
|
||||
if ((this->mode != DISP_MODE_PRINT) && (this->disp_text_.duration_ms > 0)) {
|
||||
if ((millis() - this->disp_text_.get_duration_start()) >= this->disp_text_.duration_ms) {
|
||||
ESP_LOGD(TAG, "Effect duration of %" PRIu32 "ms expired", this->disp_text_.duration_ms);
|
||||
set_mode(DISP_MODE_PRINT);
|
||||
}
|
||||
}
|
||||
|
||||
// handle repeats...
|
||||
if (this->mode == DISP_MODE_PRINT) {
|
||||
DisplayText &disp_text_other = this->disp_text_ctrl_[DISP_MODE_OTHER];
|
||||
if (disp_text_other.repeat_on) {
|
||||
if ((millis() - disp_text_other.get_repeat_start()) >= disp_text_other.repeat_interval_ms) {
|
||||
ESP_LOGD(TAG, "Repeat interval of %" PRIu32 "ms expired", disp_text_other.repeat_interval_ms);
|
||||
set_mode(DISP_MODE_OTHER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display::set_demo_mode(DemoModeT mode, uint32_t interval, uint8_t cycle_num) {
|
||||
uint text_idx, font_idx;
|
||||
DisplayText &disp_text = this->disp_text_ctrl_[DISP_MODE_OTHER];
|
||||
|
||||
ESP_LOGD(TAG, "Set demo mode: mode=%i, update-interval=%" PRIu32 "ms, cycle_num=%u", mode, interval, cycle_num);
|
||||
|
||||
|
@ -351,26 +361,25 @@ void Display::set_demo_mode(DemoModeT mode, uint32_t interval, uint8_t cycle_num
|
|||
case DEMO_MODE_SCROLL_FONT:
|
||||
// generate scroll text based on font...
|
||||
for (text_idx = 0, font_idx = 0; font_idx < ARRAY_ELEM_COUNT(ASCII_TO_SEG); font_idx++) {
|
||||
if (this->ascii_out_data_[font_idx] > 0) // displayable character?
|
||||
this->disp_text_.text[text_idx++] = ' ' + font_idx; // add character to string
|
||||
if (text_idx >= sizeof(this->disp_text_.text) - 1) { // max. text buffer lenght reached?
|
||||
if (this->ascii_out_data_[font_idx] > 0) // displayable character?
|
||||
disp_text.text[text_idx++] = ' ' + font_idx; // add character to string
|
||||
if (text_idx >= sizeof(disp_text.text) - 1) { // max. text buffer lenght reached?
|
||||
ESP_LOGD(TAG, "Font too large for internal text buffer");
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->disp_text_.text[text_idx] = 0;
|
||||
ESP_LOGV(TAG, "%s(): text: %s", __func__, this->disp_text_.text);
|
||||
disp_text.text[text_idx] = 0;
|
||||
ESP_LOGV(TAG, "%s(): text: %s", __func__, disp_text.text);
|
||||
// set text effect...
|
||||
this->disp_text_.set_text_effect(TEXT_EFFECT_SCROLL_LEFT, cycle_num);
|
||||
disp_text.set_text_effect(TEXT_EFFECT_SCROLL_LEFT, cycle_num, interval);
|
||||
disp_text.set_duration(0);
|
||||
disp_text.set_repeats(0, 0);
|
||||
set_mode(DISP_MODE_OTHER);
|
||||
break;
|
||||
default:
|
||||
set_mode(DISP_MODE_PRINT);
|
||||
break;
|
||||
}
|
||||
if ((mode != DEMO_MODE_OFF) && (interval > 0))
|
||||
set_update_interval(interval);
|
||||
clear();
|
||||
}
|
||||
|
||||
void Display::set_demo_mode(const std::string &mode, uint32_t interval, uint8_t cycle_num) {
|
||||
|
@ -383,6 +392,62 @@ void Display::set_demo_mode(const std::string &mode, uint32_t interval, uint8_t
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the display mode.
|
||||
*
|
||||
* @param mode display mode to set
|
||||
*
|
||||
* @return current mode
|
||||
*/
|
||||
DisplayModeT Display::set_mode(DisplayModeT mode) {
|
||||
this->disp_text_ = this->disp_text_ctrl_[DisplayMode::set_mode(mode)];
|
||||
|
||||
switch (this->mode) {
|
||||
case DISP_MODE_PRINT: {
|
||||
clear(); // clear display buffer
|
||||
restore_update_interval();
|
||||
// handle repeats of "other" mode...
|
||||
DisplayText &disp_text_other = this->disp_text_ctrl_[DISP_MODE_OTHER];
|
||||
if (disp_text_other.repeat_on) {
|
||||
if (disp_text_other.repeat_num > 0) { // defined number of repeats?
|
||||
if (disp_text_other.repeat_current < disp_text_other.repeat_num) {
|
||||
ESP_LOGV(TAG, "Repeat cycle finished (%u left)",
|
||||
disp_text_other.repeat_num - disp_text_other.repeat_current);
|
||||
++disp_text_other.repeat_current;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Repeats finished");
|
||||
disp_text_other.repeat_on = false;
|
||||
}
|
||||
}
|
||||
if (disp_text_other.repeat_on)
|
||||
disp_text_other.start_repeat();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DISP_MODE_OTHER: {
|
||||
clear(); // clear display buffer
|
||||
if (this->disp_text_.effect == TEXT_EFFECT_NONE) {
|
||||
update_out_buf_(); // show static text again
|
||||
} else {
|
||||
set_update_interval(this->disp_text_.update_interval_ms);
|
||||
}
|
||||
this->disp_text_.start_duration();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ESP_LOGE(TAG, "Invalid display mode: %i", this->mode);
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Set display mode: mode=%i, repeat-on=%i, repeat-cur/num=%u/%u, repeat-start=%" PRIu32 "ms", this->mode,
|
||||
this->disp_text_.repeat_on, this->disp_text_.repeat_current, this->disp_text_.repeat_num,
|
||||
this->disp_text_.get_repeat_start());
|
||||
|
||||
return this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Triggered by action. Shows the given text on the display.
|
||||
*
|
||||
|
@ -391,35 +456,55 @@ void Display::set_demo_mode(const std::string &mode, uint32_t interval, uint8_t
|
|||
* @param align text alignment
|
||||
* @param duration text effect duration in ms
|
||||
* @param effect text effect
|
||||
* @param interval text effect update interval in ms
|
||||
* @param cycle_num text effect cycle count
|
||||
* @param effect_cycle_num text effect cycle count
|
||||
* @param repeat_num text repeat count (needs duration or effect_cycle_num)
|
||||
* @param repeat_interval text repeat interval in ms (needs duration or effect_cycle_num)
|
||||
* @param update_interval text effect update interval in ms
|
||||
*
|
||||
* @return number of characters displayed
|
||||
*/
|
||||
int Display::set_text(const std::string &text, uint8_t start_pos, const std::string &align, uint32_t duration,
|
||||
const std::string &effect, uint32_t interval, uint8_t cycle_num) {
|
||||
ESP_LOGD(TAG,
|
||||
const std::string &effect, uint8_t effect_cycle_num, uint8_t repeat_num, uint32_t repeat_interval,
|
||||
uint32_t update_interval) {
|
||||
DisplayText &disp_text = this->disp_text_ctrl_[DISP_MODE_OTHER];
|
||||
|
||||
ESP_LOGV(TAG,
|
||||
"Set text (given): text=%s, start-pos=%u, align=%s, duration=%" PRIu32 "ms, "
|
||||
"effect=%s, effect-update-interval=%" PRIu32 "ms, cycles=%u",
|
||||
text.c_str(), start_pos, align.c_str(), duration, effect.c_str(), interval, cycle_num);
|
||||
"effect=%s, cycles=%u, repeat-num=%u, repeat-interval=%" PRIu32 "ms, "
|
||||
"effect-update-interval=%" PRIu32 "ms",
|
||||
text.c_str(), start_pos, align.c_str(), duration, effect.c_str(), effect_cycle_num, repeat_num,
|
||||
repeat_interval, update_interval);
|
||||
|
||||
// store new text...
|
||||
this->disp_text_.set_text(start_pos, this->num_digits_ - 1, text);
|
||||
disp_text.set_text(start_pos, this->num_digits_ - 1, text);
|
||||
|
||||
// set text align...
|
||||
this->disp_text_.set_text_align(align);
|
||||
disp_text.set_text_align(align);
|
||||
|
||||
// set text effect...
|
||||
this->disp_text_.set_text_effect(effect, cycle_num);
|
||||
if ((this->disp_text_.effect != TEXT_EFFECT_NONE) && (interval > 0)) {
|
||||
set_update_interval(interval);
|
||||
disp_text.set_text_effect(effect, effect_cycle_num, update_interval);
|
||||
if (disp_text.effect == TEXT_EFFECT_NONE)
|
||||
effect_cycle_num = 0;
|
||||
|
||||
// set duration...
|
||||
disp_text.set_duration(duration);
|
||||
disp_text.start_duration();
|
||||
|
||||
// set repeats...
|
||||
if ((effect_cycle_num == 0) && (duration == 0)) {
|
||||
repeat_num = 0;
|
||||
repeat_interval = 0;
|
||||
}
|
||||
disp_text.set_repeats(repeat_num, repeat_interval);
|
||||
|
||||
// update display mode...
|
||||
set_mode(DISP_MODE_OTHER, duration);
|
||||
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);
|
||||
ESP_LOGV(TAG,
|
||||
"Set text (result): text=%s, start-pos=%u, vi-idx=%u, vi-len=%u, "
|
||||
"duration=%" PRIu32 "ms, repeat-on=%i, repeat-num=%u, repeat-interval=%" PRIu32 "ms",
|
||||
disp_text.text, disp_text.start_pos, disp_text.visible_idx, disp_text.visible_len, disp_text.duration_ms,
|
||||
disp_text.repeat_on, disp_text.repeat_num, disp_text.repeat_interval_ms);
|
||||
|
||||
return update_out_buf_();
|
||||
}
|
||||
|
@ -433,14 +518,16 @@ int Display::set_text(const std::string &text, uint8_t start_pos, const std::str
|
|||
* @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);
|
||||
DisplayText &disp_text = this->disp_text_ctrl_[DISP_MODE_PRINT];
|
||||
|
||||
ESP_LOGVV(TAG, "%s(): str=%s, prev=%s", __func__, text, disp_text.text);
|
||||
if (strncmp(text, disp_text.text, sizeof(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, disp_text.text);
|
||||
|
||||
// store new text...
|
||||
std::string text_str = text;
|
||||
this->disp_text_.set_text(start_pos, this->num_digits_ - 1, text_str);
|
||||
disp_text.set_text(start_pos, this->num_digits_ - 1, text_str);
|
||||
|
||||
return update_out_buf_();
|
||||
}
|
||||
|
@ -554,6 +641,55 @@ DisplayText::DisplayText() {
|
|||
this->max_pos = 0;
|
||||
this->align = TEXT_ALIGN_CENTER;
|
||||
this->effect = TEXT_EFFECT_NONE;
|
||||
this->cycle_num = 0; // endless
|
||||
this->cycle_current = 0;
|
||||
this->update_interval_ms = 0;
|
||||
this->duration_ms = 0; // endless
|
||||
this->repeat_on = false;
|
||||
this->repeat_num = 0; // endless repeats
|
||||
this->repeat_current = 0;
|
||||
this->repeat_interval_ms = 0; // no repeat
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the text display time.
|
||||
*
|
||||
* @param duration_ms text display time in [ms]
|
||||
*/
|
||||
void DisplayText::set_duration(uint32_t duration_ms) {
|
||||
ESP_LOGD(TAG, "Set text duration: %" PRIu32 "ms", duration_ms);
|
||||
this->duration_ms = duration_ms;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the text display time period.
|
||||
*/
|
||||
void DisplayText::start_duration() {
|
||||
if (this->duration_ms > 0) {
|
||||
ESP_LOGV(TAG, "Start text duration (%" PRIu32 "ms)", this->duration_ms);
|
||||
this->duration_ms_start_ = millis();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the text display repeat interval(s) after duration has expired.
|
||||
*
|
||||
* @param repeat_num text display repeat number (0 = endless)
|
||||
* @param repeat_interval_ms text display repeat interval [ms]
|
||||
*/
|
||||
void DisplayText::set_repeats(uint8_t repeat_num, uint32_t repeat_interval_ms) {
|
||||
this->repeat_num = repeat_num;
|
||||
this->repeat_current = 0;
|
||||
this->repeat_interval_ms = repeat_interval_ms;
|
||||
this->repeat_on = (repeat_interval_ms > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the text display repeat period.
|
||||
*/
|
||||
void DisplayText::start_repeat() {
|
||||
if (this->repeat_interval_ms > 0)
|
||||
this->repeat_ms_start_ = millis();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -578,6 +714,10 @@ int DisplayText::set_text(uint start_pos, uint max_pos, const std::string &text)
|
|||
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);
|
||||
|
||||
ESP_LOGD(TAG, "Set text: start-pos=%u, vi-idx=%u, vi-len=%u, text=%s", this->start_pos, this->visible_idx,
|
||||
this->visible_len, this->text);
|
||||
|
||||
return strlen(this->text);
|
||||
}
|
||||
|
||||
|
@ -633,7 +773,7 @@ void DisplayText::set_text_align(TextAlignT align) {
|
|||
}
|
||||
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,
|
||||
ESP_LOGD(TAG, "Set text align: align=%i, start-pos=%u, max-pos=%u, vi-idx=%u, vi-len=%u", this->align,
|
||||
this->start_pos, this->max_pos, this->visible_idx, this->visible_len);
|
||||
}
|
||||
|
||||
|
@ -667,22 +807,31 @@ void DisplayText::set_text_align(const std::string &align) {
|
|||
*
|
||||
* @param effect text effect
|
||||
* @param cycle_num number of effect cycles (optional, default=endless)
|
||||
* @param update_interval effect update interval in [ms] (optional, default=standard)
|
||||
*/
|
||||
void DisplayText::set_text_effect(TextEffectT effect, uint8_t cycle_num) {
|
||||
void DisplayText::set_text_effect(TextEffectT effect, uint8_t cycle_num, uint32_t update_interval) {
|
||||
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;
|
||||
if (effect == TEXT_EFFECT_BLINK)
|
||||
this->effect_change_count_ = -1;
|
||||
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);
|
||||
|
||||
this->effect = effect;
|
||||
switch (effect) {
|
||||
case TEXT_EFFECT_BLINK:
|
||||
case TEXT_EFFECT_SCROLL_LEFT:
|
||||
this->cycle_current = 1;
|
||||
this->cycle_num = cycle_num;
|
||||
this->update_interval_ms = update_interval;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
init_text_effect_();
|
||||
ESP_LOGD(TAG,
|
||||
"Set text effect: effect=%i, cycles=%u, upd-interval=%" PRIu32 "ms, start-pos=%u, "
|
||||
"max-pos=%u, vi-idx=%u, vi-len=%u",
|
||||
this->effect, this->cycle_num, this->update_interval_ms, this->start_pos, this->max_pos, this->visible_idx,
|
||||
this->visible_len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -690,8 +839,9 @@ void DisplayText::set_text_effect(TextEffectT effect, uint8_t cycle_num) {
|
|||
*
|
||||
* @param effect text effect (as string)
|
||||
* @param cycle_num number of effect cycles (optional, default=endless)
|
||||
* @param update_interval effect update interval in [ms] (optional, default=standard)
|
||||
*/
|
||||
void DisplayText::set_text_effect(const std::string &effect, uint8_t cycle_num) {
|
||||
void DisplayText::set_text_effect(const std::string &effect, uint8_t cycle_num, uint32_t update_interval) {
|
||||
TextEffectT text_effect = TEXT_EFFECT_LAST_ENUM;
|
||||
|
||||
if (!effect.empty()) {
|
||||
|
@ -708,56 +858,61 @@ void DisplayText::set_text_effect(const std::string &effect, uint8_t cycle_num)
|
|||
ESP_LOGW(TAG, "No text effect given");
|
||||
if (text_effect >= TEXT_EFFECT_LAST_ENUM)
|
||||
return;
|
||||
set_text_effect(text_effect, cycle_num);
|
||||
set_text_effect(text_effect, cycle_num, update_interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the mode "blink". The display buffer must be updated before.
|
||||
*
|
||||
* @return true = effect cycles finished
|
||||
* false = effect cycles not finished
|
||||
*/
|
||||
void DisplayText::blink() {
|
||||
ESP_LOGV(TAG, "%s(): ENTRY: start-idx=%u, text-idx=%u, text-len=%u", __func__, this->start_pos, this->visible_idx,
|
||||
this->visible_len);
|
||||
bool DisplayText::blink() {
|
||||
ESP_LOGV(TAG, "%s(): ENTRY: start-idx=%u, text-idx=%u, text-len=%u, cycle-cur/num=%u/%u", __func__, this->start_pos,
|
||||
this->visible_idx, this->visible_len, this->cycle_current, this->cycle_num);
|
||||
|
||||
// update effect mode...
|
||||
if (++this->effect_change_count_ >= 2) { // one on/off phase complete?
|
||||
this->effect_change_count_ = 0;
|
||||
if (this->cycle_num > 0) {
|
||||
ESP_LOGD(TAG, "Blink cycle finished (%u left)", this->cycle_num - 1);
|
||||
if (--this->cycle_num == 0) {
|
||||
this->effect = TEXT_EFFECT_NONE;
|
||||
ESP_LOGD(TAG, "Blink finished");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((this->cycle_num > 0) && (this->cycle_current > this->cycle_num)) { // cycles finished?
|
||||
ESP_LOGD(TAG, "Blink finished");
|
||||
return true;
|
||||
}
|
||||
|
||||
// update visible text...
|
||||
if (this->visible_len > 0) { // "on" phase?
|
||||
this->visible_len = 0; // yes -> switch to "off" phase
|
||||
} else {
|
||||
init_text_effect_(); // no -> switch to "on" phase
|
||||
this->visible_len = 0; // yes -> next display buffer update starts "off" phase
|
||||
} else { // "off" phase...
|
||||
ESP_LOGV(TAG, "\"Off\" phase of blink cycle started (%u cycles left)", this->cycle_num - this->cycle_current);
|
||||
if ((this->cycle_num == 0) || // endless cycles or
|
||||
(this->cycle_current < this->cycle_num)) { // number of cycles not finished?
|
||||
init_text_effect_(); // next display buffer update starts "on" phase
|
||||
}
|
||||
if (this->cycle_num > 0) // defined number of cycles?
|
||||
++this->cycle_current; // yes -> increase current cycle count
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "%s(): EXIT: start-idx=%u, text-idx=%u, text-len=%u", __func__, this->start_pos, this->visible_idx,
|
||||
this->visible_len);
|
||||
ESP_LOGV(TAG, "%s(): EXIT: start-idx=%u, text-idx=%u, text-len=%u, cycle-cur/num=%u/%u", __func__, this->start_pos,
|
||||
this->visible_idx, this->visible_len, this->cycle_current, this->cycle_num);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the mode "scroll left". The display buffer must be updated before.
|
||||
*
|
||||
* @return true = effect cycles finished
|
||||
* false = effect cycles not finished
|
||||
*/
|
||||
void DisplayText::scroll_left() {
|
||||
bool DisplayText::scroll_left() {
|
||||
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 effect mode...
|
||||
if (this->visible_len == 0) {
|
||||
if (this->visible_len == 0) { // cycle finished?
|
||||
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;
|
||||
if (this->cycle_current <= this->cycle_num) {
|
||||
ESP_LOGV(TAG, "Scroll cycle finished (%u left)", this->cycle_num - this->cycle_current);
|
||||
if (this->cycle_current++ >= this->cycle_num) {
|
||||
ESP_LOGD(TAG, "Scroll finished");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -775,6 +930,8 @@ void DisplayText::scroll_left() {
|
|||
|
||||
ESP_LOGV(TAG, "%s(): EXIT: start-idx=%u, text-idx=%u, text-len=%u", __func__, this->start_pos, this->visible_idx,
|
||||
this->visible_len);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -820,31 +977,25 @@ void DisplayBrightness::set_brightness(float percent) {
|
|||
/**
|
||||
* @brief Constructor.
|
||||
*/
|
||||
DisplayMode::DisplayMode() {
|
||||
this->mode = DISP_MODE_PRINT;
|
||||
this->duration_ms = 0; // endless
|
||||
}
|
||||
DisplayMode::DisplayMode() { this->mode = DISP_MODE_PRINT; }
|
||||
|
||||
/**
|
||||
* @brief Sets the display mode.
|
||||
*
|
||||
* @param mode display start position of text (0..n)
|
||||
* @param duration duration in ms (optional, default=endless)
|
||||
* not applicable for "it" mode
|
||||
* @param mode display mode to set
|
||||
*
|
||||
* @return current mode
|
||||
*/
|
||||
void DisplayMode::set_mode(DisplayModeT mode, uint32_t duration_ms) {
|
||||
DisplayModeT DisplayMode::set_mode(DisplayModeT mode) {
|
||||
if (mode >= DISP_MODE_LAST_ENUM) {
|
||||
ESP_LOGE(TAG, "Invalid display mode: %i", mode);
|
||||
return;
|
||||
return this->mode;
|
||||
}
|
||||
if (mode != this->mode) {
|
||||
this->mode = mode;
|
||||
this->duration_ms = duration_ms;
|
||||
if (duration_ms > 0)
|
||||
this->duration_ms_start_ = millis();
|
||||
ESP_LOGD(TAG, "Set display mode: mode=%i, duration=%" PRIu32 "ms, duration-start=%" PRIu32 "ms", this->mode,
|
||||
this->duration_ms, this->duration_ms_start_);
|
||||
}
|
||||
|
||||
return this->mode;
|
||||
}
|
||||
|
||||
} // namespace max6921
|
||||
|
|
|
@ -16,8 +16,9 @@ static const uint FONT_SIZE = 95;
|
|||
static const uint DISPLAY_TEXT_LEN = FONT_SIZE; // at least font size for demo mode "scroll font"
|
||||
|
||||
enum DisplayModeT {
|
||||
DISP_MODE_PRINT, // input by it-functions
|
||||
DISP_MODE_OTHER, // input by actions
|
||||
// Used as index!
|
||||
DISP_MODE_PRINT = 0, // input by it-functions
|
||||
DISP_MODE_OTHER, // input by actions
|
||||
DISP_MODE_LAST_ENUM
|
||||
};
|
||||
|
||||
|
@ -52,17 +53,16 @@ class DisplayBrightness {
|
|||
class DisplayMode {
|
||||
public:
|
||||
DisplayModeT mode;
|
||||
uint32_t duration_ms;
|
||||
DisplayMode();
|
||||
void set_mode(DisplayModeT mode, uint32_t duration_ms = 0);
|
||||
DisplayModeT set_mode(DisplayModeT mode);
|
||||
|
||||
protected:
|
||||
uint32_t duration_ms_start_;
|
||||
};
|
||||
|
||||
class DisplayText {
|
||||
public:
|
||||
bool content_changed;
|
||||
bool repeat_on; // repetitions are enabled
|
||||
uint max_pos; // max. display position
|
||||
uint start_pos; // current display start position (0..n)
|
||||
char text[DISPLAY_TEXT_LEN + 1]; // current text to display (may be larger then display)
|
||||
|
@ -70,18 +70,31 @@ class DisplayText {
|
|||
uint visible_len; // current length of visible text
|
||||
TextAlignT align;
|
||||
TextEffectT effect;
|
||||
uint8_t cycle_num;
|
||||
uint32_t duration_ms; // text/effect duration
|
||||
uint32_t repeat_interval_ms; // repeat interval
|
||||
uint8_t repeat_num; // number of repeats of showing text/effect
|
||||
uint8_t repeat_current; // current repeat cycle
|
||||
uint8_t cycle_num; // number of effect cycles
|
||||
uint8_t cycle_current; // current effect cycle
|
||||
uint32_t update_interval_ms; // effect update interval
|
||||
DisplayText();
|
||||
void blink();
|
||||
void scroll_left();
|
||||
bool blink();
|
||||
uint32_t get_duration_start() { return this->duration_ms_start_; }
|
||||
uint32_t get_repeat_start() { return this->repeat_ms_start_; }
|
||||
bool scroll_left();
|
||||
void set_duration(uint32_t duration_ms);
|
||||
void start_duration();
|
||||
void start_repeat();
|
||||
void set_repeats(uint8_t repeat_num, uint32_t repeat_interval_ms);
|
||||
int set_text(uint start_pos, uint max_pos, const std::string &text);
|
||||
void set_text_align(TextAlignT align);
|
||||
void set_text_align(const std::string &align);
|
||||
void set_text_effect(TextEffectT effect, uint8_t cycle_num = 0);
|
||||
void set_text_effect(const std::string &effect, uint8_t cycle_num = 0);
|
||||
void set_text_effect(TextEffectT effect, uint8_t cycle_num = 0, uint32_t update_interval = 0);
|
||||
void set_text_effect(const std::string &effect, uint8_t cycle_num = 0, uint32_t update_interval = 0);
|
||||
|
||||
protected:
|
||||
int effect_change_count_;
|
||||
uint32_t duration_ms_start_;
|
||||
uint32_t repeat_ms_start_;
|
||||
void init_text_align_();
|
||||
void init_text_effect_();
|
||||
};
|
||||
|
@ -96,9 +109,11 @@ class Display : public DisplayBrightness, public DisplayMode {
|
|||
void setup(std::vector<uint8_t> &seg_to_out_map, std::vector<uint8_t> &pos_to_out_map);
|
||||
void set_demo_mode(DemoModeT mode, uint32_t interval, uint8_t cycle_num);
|
||||
void set_demo_mode(const std::string &mode, uint32_t interval, uint8_t cycle_num);
|
||||
DisplayModeT set_mode(DisplayModeT mode);
|
||||
int set_text(const char *text, uint8_t start_pos);
|
||||
int set_text(const std::string &text, uint8_t start_pos, const std::string &align, uint32_t duration,
|
||||
const std::string &effect, uint32_t interval, uint8_t cycle_num);
|
||||
const std::string &effect, uint8_t effect_cycle_num, uint8_t repeat_num, uint32_t repeat_interval,
|
||||
uint32_t update_interval);
|
||||
void set_update_interval(uint32_t interval_ms);
|
||||
void update();
|
||||
|
||||
|
@ -112,7 +127,8 @@ class Display : public DisplayBrightness, public DisplayMode {
|
|||
size_t out_buf_size_;
|
||||
uint seg_out_smallest_;
|
||||
uint32_t refresh_period_us_;
|
||||
DisplayText disp_text_;
|
||||
DisplayText disp_text_ctrl_[DISP_MODE_LAST_ENUM];
|
||||
DisplayText &disp_text_ = disp_text_ctrl_[0];
|
||||
uint32_t default_update_interval_;
|
||||
static void display_refresh_task(void *pv);
|
||||
int update_out_buf_();
|
||||
|
|
|
@ -44,11 +44,13 @@ CONF_POS_11_PIN = "pos_11_pin"
|
|||
CONF_POS_12_PIN = "pos_12_pin"
|
||||
# CONF_DEMO_MODE = "demo_mode"
|
||||
CONF_ALIGN = "align"
|
||||
CONF_EFFECT_CYCLE_NUM = "effect_cycle_num"
|
||||
CONF_CYCLE_NUM = "cycle_num"
|
||||
CONF_OFF = "off"
|
||||
CONF_REPEAT_INTERVAL = "repeat_interval"
|
||||
CONF_REPEAT_NUM = "repeat_num"
|
||||
CONF_SCROLL_FONT = "scroll_font"
|
||||
|
||||
|
||||
max6921_ns = cg.esphome_ns.namespace("max6921")
|
||||
MAX6921Component = max6921_ns.class_(
|
||||
"MAX6921Component", cg.PollingComponent, spi.SPIDevice
|
||||
|
@ -208,13 +210,27 @@ async def max6921_set_brightness_to_code(config, action_id, template_arg, args):
|
|||
|
||||
|
||||
def validate_action_set_text(value):
|
||||
# duration = value.get(CONF_DURATION)
|
||||
# cycle_num = value.get(CONF_CYCLE_NUM)
|
||||
# if not isinstance(duration, cv.Lambda) and not isinstance(cycle_num, cv.Lambda):
|
||||
# if duration.total_milliseconds > 0 and cycle_num > 0:
|
||||
# raise cv.Invalid(
|
||||
# f"Only one of following config value must be set: {CONF_CYCLE_NUM}, {CONF_DURATION}"
|
||||
# )
|
||||
duration = value.get(CONF_DURATION)
|
||||
effect_cycle_num = value.get(CONF_EFFECT_CYCLE_NUM)
|
||||
repeat_interval = value.get(CONF_REPEAT_INTERVAL)
|
||||
repeat_num = value.get(CONF_REPEAT_NUM)
|
||||
if (
|
||||
not isinstance(duration, cv.Lambda)
|
||||
and not isinstance(effect_cycle_num, cv.Lambda)
|
||||
and not isinstance(repeat_interval, cv.Lambda)
|
||||
and not isinstance(repeat_num, cv.Lambda)
|
||||
):
|
||||
if ((repeat_interval.total_milliseconds > 0) or (repeat_num > 0)) and (
|
||||
(effect_cycle_num == 0) and (duration.total_milliseconds == 0)
|
||||
):
|
||||
raise cv.Invalid(
|
||||
f'If "{CONF_REPEAT_INTERVAL}" or "{CONF_REPEAT_NUM}" is non-zero, '
|
||||
f'then "{CONF_EFFECT_CYCLE_NUM}" or "{CONF_DURATION}" must be non-zero too'
|
||||
)
|
||||
if (repeat_num > 0) and (repeat_interval.total_milliseconds == 0):
|
||||
raise cv.Invalid(
|
||||
f'If "{CONF_REPEAT_NUM}" is non-zero, then "{CONF_REPEAT_INTERVAL}" must be non-zero too'
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
|
@ -234,10 +250,16 @@ ACTION_SET_TEXT_SCHEMA = cv.All(
|
|||
cv.positive_time_period_milliseconds
|
||||
),
|
||||
cv.Optional(CONF_EFFECT, default="none"): cv.templatable(cv.string),
|
||||
cv.Optional(CONF_EFFECT_CYCLE_NUM, default=0): cv.templatable(
|
||||
cv.uint8_t
|
||||
),
|
||||
cv.Optional(CONF_REPEAT_INTERVAL, default="0ms"): cv.templatable(
|
||||
cv.positive_time_period_milliseconds
|
||||
),
|
||||
cv.Optional(CONF_REPEAT_NUM, default=0): cv.templatable(cv.uint8_t),
|
||||
cv.Optional(CONF_UPDATE_INTERVAL, default="150ms"): cv.templatable(
|
||||
cv.positive_time_period_milliseconds
|
||||
),
|
||||
cv.Optional(CONF_CYCLE_NUM, default=0): cv.templatable(cv.uint8_t),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
@ -264,12 +286,18 @@ async def max6921_set_text_to_code(config, action_id, template_arg, args):
|
|||
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_EFFECT_CYCLE_NUM in config:
|
||||
template_ = await cg.templatable(config[CONF_EFFECT_CYCLE_NUM], args, cg.uint8)
|
||||
cg.add(var.set_text_effect_cycle_num(template_))
|
||||
if CONF_REPEAT_NUM in config:
|
||||
template_ = await cg.templatable(config[CONF_REPEAT_NUM], args, cg.uint8)
|
||||
cg.add(var.set_text_repeat_num(template_))
|
||||
if CONF_REPEAT_INTERVAL in config:
|
||||
template_ = await cg.templatable(config[CONF_REPEAT_INTERVAL], args, cg.uint32)
|
||||
cg.add(var.set_text_repeat_interval(template_))
|
||||
if CONF_UPDATE_INTERVAL in config:
|
||||
template_ = await cg.templatable(config[CONF_UPDATE_INTERVAL], args, cg.uint32)
|
||||
cg.add(var.set_text_effect_update_interval(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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue