MAX9621: fix CI errors

This commit is contained in:
endym 2024-08-08 16:06:36 +02:00
parent 567023cf31
commit e3d3e619af
6 changed files with 275 additions and 325 deletions

View file

@ -16,7 +16,6 @@ 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) {}
@ -34,20 +33,14 @@ template<typename... Ts> class SetTextAction : public Action<Ts...> {
auto cycle_num = this->text_effect_cycle_num_.value(x...);
auto duration = this->text_effect_duration_.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->max9621_->display_->set_text(this->text_.value(x...), pos, this->text_align_.value(x...), duration,
this->text_effect_.value(x...), update_interval, cycle_num);
}
protected:
MAX6921Component *max9621_;
};
#if 0
template<typename... Ts> class SetDemoModeAction : public Action<Ts...>, public Parented<MAX6921Component> {
public:
@ -60,7 +53,6 @@ template<typename... Ts> class SetDemoModeAction : public Action<Ts...>, public
};
#endif
template<typename... Ts> class SetDemoModeAction : public Action<Ts...> {
public:
explicit SetDemoModeAction(MAX6921Component *max9621) : max9621_(max9621) {}
@ -76,17 +68,15 @@ template<typename... Ts> class SetDemoModeAction : public Action<Ts...> {
// this->set_mode(DEMO_MODE_OFF);
// } else if (str_equals_case_insensitive(mode, "scroll_font")) {
// this->set_mode(DEMO_MODE_SCROLL_FONT);
// } else {
// ESP_LOGW(TAG, "Invalid demo mode %s", mode.c_str());
// }
// } else {
// output log message (TAG, "Invalid demo mode %s", mode.c_str());
// }
// }
void play(Ts... x) override {
auto update_interval = this->demo_update_interval_.value(x...);
auto cycle_num = this->demo_cycle_num_.value(x...);
this->max9621_->display_->set_demo_mode(this->mode_.value(x...),
update_interval,
cycle_num);
this->max9621_->display_->set_demo_mode(this->mode_.value(x...), update_interval, cycle_num);
}
protected:
@ -95,6 +85,5 @@ template<typename... Ts> class SetDemoModeAction : public Action<Ts...> {
// DemoMode mode_;
};
} // namespace max9621
} // namespace max6921
} // namespace esphome

View file

@ -8,121 +8,119 @@
namespace esphome {
namespace max6921 {
static const char *const TAG = "max6921.display";
// segments of 7-segment character
static const uint8_t SEG_A = (1<<0);
static const uint8_t SEG_B = (1<<1);
static const uint8_t SEG_C = (1<<2);
static const uint8_t SEG_D = (1<<3);
static const uint8_t SEG_E = (1<<4);
static const uint8_t SEG_F = (1<<5);
static const uint8_t SEG_G = (1<<6);
static const uint8_t SEG_DP = (1<<7);
static const uint8_t SEG_A = (1 << 0);
static const uint8_t SEG_B = (1 << 1);
static const uint8_t SEG_C = (1 << 2);
static const uint8_t SEG_D = (1 << 3);
static const uint8_t SEG_E = (1 << 4);
static const uint8_t SEG_F = (1 << 5);
static const uint8_t SEG_G = (1 << 6);
static const uint8_t SEG_DP = (1 << 7);
static const uint8_t SEG_UNSUPPORTED_CHAR = 0;
// ASCII table from 0x20..0x7E
const uint8_t ASCII_TO_SEG[FONT_SIZE] PROGMEM = {
0, // ' ', (0x20)
SEG_UNSUPPORTED_CHAR, // '!', (0x21)
SEG_B|SEG_F, // '"', (0x22)
SEG_UNSUPPORTED_CHAR, // '#', (0x23)
SEG_UNSUPPORTED_CHAR, // '$', (0x24)
SEG_UNSUPPORTED_CHAR, // '%', (0x25)
SEG_UNSUPPORTED_CHAR, // '&', (0x26)
SEG_F, // ''', (0x27)
SEG_A|SEG_D|SEG_E|SEG_F, // '(', (0x28)
SEG_A|SEG_B|SEG_C|SEG_D, // ')', (0x29)
SEG_UNSUPPORTED_CHAR, // '*', (0x2A)
SEG_UNSUPPORTED_CHAR, // '+', (0x2B)
SEG_DP, // ',', (0x2C)
SEG_G, // '-', (0x2D)
SEG_DP, // '.', (0x2E)
SEG_UNSUPPORTED_CHAR, // '/', (0x2F)
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F, // '0', (0x30)
SEG_B|SEG_C, // '1', (0x31)
SEG_A|SEG_B|SEG_D|SEG_E|SEG_G, // '2', (0x32)
SEG_A|SEG_B|SEG_C|SEG_D|SEG_G, // '3', (0x33)
SEG_B|SEG_C|SEG_F|SEG_G, // '4', (0x34)
SEG_A|SEG_C|SEG_D|SEG_F|SEG_G, // '5', (0x35)
SEG_A|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G, // '6', (0x36)
SEG_A|SEG_B|SEG_C, // '7', (0x37)
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G, // '8', (0x38)
SEG_A|SEG_B|SEG_C|SEG_D|SEG_F|SEG_G, // '9', (0x39)
SEG_UNSUPPORTED_CHAR, // ':', (0x3A)
SEG_UNSUPPORTED_CHAR, // ';', (0x3B)
SEG_UNSUPPORTED_CHAR, // '<', (0x3C)
SEG_D|SEG_G, // '=', (0x3D)
SEG_UNSUPPORTED_CHAR, // '>', (0x3E)
SEG_A|SEG_B|SEG_E|SEG_G, // '?', (0x3F)
SEG_A|SEG_B|SEG_D|SEG_E|SEG_F|SEG_G, // '@', (0x40)
SEG_A|SEG_B|SEG_C|SEG_E|SEG_F|SEG_G, // 'A', (0x41)
SEG_C|SEG_D|SEG_E|SEG_F|SEG_G, // 'B', (0x42)
SEG_A|SEG_D|SEG_E|SEG_F, // 'C', (0x43)
SEG_B|SEG_C|SEG_D|SEG_E|SEG_G, // 'D', (0x44)
SEG_A|SEG_D|SEG_E|SEG_F|SEG_G, // 'E', (0x45)
SEG_A|SEG_E|SEG_F|SEG_G, // 'F', (0x46)
SEG_A|SEG_C|SEG_D|SEG_E|SEG_F, // 'G', (0x47)
SEG_B|SEG_C|SEG_E|SEG_F|SEG_G, // 'H', (0x48)
SEG_B|SEG_C, // 'I', (0x49)
SEG_B|SEG_C|SEG_D|SEG_E, // 'J', (0x4A)
SEG_UNSUPPORTED_CHAR, // 'K', (0x4B)
SEG_D|SEG_E|SEG_F, // 'L', (0x4C)
SEG_UNSUPPORTED_CHAR, // 'M', (0x4D)
SEG_C|SEG_E|SEG_G, // 'N', (0x4E)
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F, // 'O', (0x4F)
SEG_A|SEG_B|SEG_E|SEG_F|SEG_G, // 'P', (0x50)
SEG_UNSUPPORTED_CHAR, // 'Q', (0x51)
SEG_E|SEG_G, // 'R', (0x52)
SEG_A|SEG_C|SEG_D|SEG_F|SEG_G, // 'S', (0x53)
SEG_UNSUPPORTED_CHAR, // 'T', (0x54)
SEG_B|SEG_C|SEG_D|SEG_E|SEG_F, // 'U', (0x55)
SEG_UNSUPPORTED_CHAR, // 'V', (0x56)
SEG_UNSUPPORTED_CHAR, // 'W', (0x57)
SEG_UNSUPPORTED_CHAR, // 'X', (0x58)
SEG_B|SEG_E|SEG_F|SEG_G, // 'Y', (0x59)
SEG_UNSUPPORTED_CHAR, // 'Z', (0x5A)
SEG_A|SEG_D|SEG_E|SEG_F, // '[', (0x5B)
SEG_UNSUPPORTED_CHAR, // '\', (0x5C)
SEG_A|SEG_B|SEG_C|SEG_D, // ']', (0x5D)
SEG_UNSUPPORTED_CHAR, // '^', (0x5E)
SEG_D, // '_', (0x5F)
SEG_F, // '`', (0x60)
SEG_A|SEG_B|SEG_C|SEG_E|SEG_F|SEG_G, // 'a', (0x61)
SEG_C|SEG_D|SEG_E|SEG_F|SEG_G, // 'b', (0x62)
SEG_D|SEG_E|SEG_G, // 'c', (0x63)
SEG_B|SEG_C|SEG_D|SEG_E|SEG_G, // 'd', (0x64)
SEG_A|SEG_D|SEG_E|SEG_F|SEG_G, // 'e', (0x65)
SEG_A|SEG_E|SEG_F|SEG_G, // 'f', (0x66)
SEG_A|SEG_C|SEG_D|SEG_E|SEG_F, // 'g', (0x67)
SEG_C|SEG_E|SEG_F|SEG_G, // 'h', (0x68)
SEG_C, // 'i', (0x69)
SEG_B|SEG_C|SEG_D|SEG_E, // 'j', (0x6A)
SEG_UNSUPPORTED_CHAR, // 'k', (0x6B)
SEG_D|SEG_E|SEG_F, // 'l', (0x6C)
SEG_UNSUPPORTED_CHAR, // 'm', (0x6D)
SEG_C|SEG_E|SEG_G, // 'n', (0x6E)
SEG_C|SEG_D|SEG_E|SEG_G, // 'o', (0x6F)
SEG_A|SEG_B|SEG_E|SEG_F|SEG_G, // 'p', (0x70)
SEG_UNSUPPORTED_CHAR, // 'q', (0x71)
SEG_E|SEG_G, // 'r', (0x72)
SEG_A|SEG_C|SEG_D|SEG_F|SEG_G, // 's', (0x73)
SEG_UNSUPPORTED_CHAR, // 't', (0x74)
SEG_C|SEG_D|SEG_E, // 'u', (0x75)
SEG_UNSUPPORTED_CHAR, // 'v', (0x76)
SEG_UNSUPPORTED_CHAR, // 'w', (0x77)
SEG_UNSUPPORTED_CHAR, // 'x', (0x78)
SEG_B|SEG_E|SEG_F|SEG_G, // 'y', (0x79)
SEG_UNSUPPORTED_CHAR, // 'z', (0x7A)
SEG_B|SEG_C|SEG_G, // '{', (0x7B)
SEG_UNSUPPORTED_CHAR, // '|', (0x7C)
SEG_E|SEG_F|SEG_G, // '}', (0x7D)
SEG_UNSUPPORTED_CHAR, // '~', (0x7E)
0, // ' ', (0x20)
SEG_UNSUPPORTED_CHAR, // '!', (0x21)
SEG_B | SEG_F, // '"', (0x22)
SEG_UNSUPPORTED_CHAR, // '#', (0x23)
SEG_UNSUPPORTED_CHAR, // '$', (0x24)
SEG_UNSUPPORTED_CHAR, // '%', (0x25)
SEG_UNSUPPORTED_CHAR, // '&', (0x26)
SEG_F, // ''', (0x27)
SEG_A | SEG_D | SEG_E | SEG_F, // '(', (0x28)
SEG_A | SEG_B | SEG_C | SEG_D, // ')', (0x29)
SEG_UNSUPPORTED_CHAR, // '*', (0x2A)
SEG_UNSUPPORTED_CHAR, // '+', (0x2B)
SEG_DP, // ',', (0x2C)
SEG_G, // '-', (0x2D)
SEG_DP, // '.', (0x2E)
SEG_UNSUPPORTED_CHAR, // '/', (0x2F)
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // '0', (0x30)
SEG_B | SEG_C, // '1', (0x31)
SEG_A | SEG_B | SEG_D | SEG_E | SEG_G, // '2', (0x32)
SEG_A | SEG_B | SEG_C | SEG_D | SEG_G, // '3', (0x33)
SEG_B | SEG_C | SEG_F | SEG_G, // '4', (0x34)
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // '5', (0x35)
SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // '6', (0x36)
SEG_A | SEG_B | SEG_C, // '7', (0x37)
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // '8', (0x38)
SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G, // '9', (0x39)
SEG_UNSUPPORTED_CHAR, // ':', (0x3A)
SEG_UNSUPPORTED_CHAR, // ';', (0x3B)
SEG_UNSUPPORTED_CHAR, // '<', (0x3C)
SEG_D | SEG_G, // '=', (0x3D)
SEG_UNSUPPORTED_CHAR, // '>', (0x3E)
SEG_A | SEG_B | SEG_E | SEG_G, // '?', (0x3F)
SEG_A | SEG_B | SEG_D | SEG_E | SEG_F | SEG_G, // '@', (0x40)
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // 'A', (0x41)
SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // 'B', (0x42)
SEG_A | SEG_D | SEG_E | SEG_F, // 'C', (0x43)
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // 'D', (0x44)
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // 'E', (0x45)
SEG_A | SEG_E | SEG_F | SEG_G, // 'F', (0x46)
SEG_A | SEG_C | SEG_D | SEG_E | SEG_F, // 'G', (0x47)
SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // 'H', (0x48)
SEG_B | SEG_C, // 'I', (0x49)
SEG_B | SEG_C | SEG_D | SEG_E, // 'J', (0x4A)
SEG_UNSUPPORTED_CHAR, // 'K', (0x4B)
SEG_D | SEG_E | SEG_F, // 'L', (0x4C)
SEG_UNSUPPORTED_CHAR, // 'M', (0x4D)
SEG_C | SEG_E | SEG_G, // 'N', (0x4E)
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // 'O', (0x4F)
SEG_A | SEG_B | SEG_E | SEG_F | SEG_G, // 'P', (0x50)
SEG_UNSUPPORTED_CHAR, // 'Q', (0x51)
SEG_E | SEG_G, // 'R', (0x52)
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // 'S', (0x53)
SEG_UNSUPPORTED_CHAR, // 'T', (0x54)
SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // 'U', (0x55)
SEG_UNSUPPORTED_CHAR, // 'V', (0x56)
SEG_UNSUPPORTED_CHAR, // 'W', (0x57)
SEG_UNSUPPORTED_CHAR, // 'X', (0x58)
SEG_B | SEG_E | SEG_F | SEG_G, // 'Y', (0x59)
SEG_UNSUPPORTED_CHAR, // 'Z', (0x5A)
SEG_A | SEG_D | SEG_E | SEG_F, // '[', (0x5B)
SEG_UNSUPPORTED_CHAR, // '\', (0x5C)
SEG_A | SEG_B | SEG_C | SEG_D, // ']', (0x5D)
SEG_UNSUPPORTED_CHAR, // '^', (0x5E)
SEG_D, // '_', (0x5F)
SEG_F, // '`', (0x60)
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // 'a', (0x61)
SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, // 'b', (0x62)
SEG_D | SEG_E | SEG_G, // 'c', (0x63)
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // 'd', (0x64)
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // 'e', (0x65)
SEG_A | SEG_E | SEG_F | SEG_G, // 'f', (0x66)
SEG_A | SEG_C | SEG_D | SEG_E | SEG_F, // 'g', (0x67)
SEG_C | SEG_E | SEG_F | SEG_G, // 'h', (0x68)
SEG_C, // 'i', (0x69)
SEG_B | SEG_C | SEG_D | SEG_E, // 'j', (0x6A)
SEG_UNSUPPORTED_CHAR, // 'k', (0x6B)
SEG_D | SEG_E | SEG_F, // 'l', (0x6C)
SEG_UNSUPPORTED_CHAR, // 'm', (0x6D)
SEG_C | SEG_E | SEG_G, // 'n', (0x6E)
SEG_C | SEG_D | SEG_E | SEG_G, // 'o', (0x6F)
SEG_A | SEG_B | SEG_E | SEG_F | SEG_G, // 'p', (0x70)
SEG_UNSUPPORTED_CHAR, // 'q', (0x71)
SEG_E | SEG_G, // 'r', (0x72)
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // 's', (0x73)
SEG_UNSUPPORTED_CHAR, // 't', (0x74)
SEG_C | SEG_D | SEG_E, // 'u', (0x75)
SEG_UNSUPPORTED_CHAR, // 'v', (0x76)
SEG_UNSUPPORTED_CHAR, // 'w', (0x77)
SEG_UNSUPPORTED_CHAR, // 'x', (0x78)
SEG_B | SEG_E | SEG_F | SEG_G, // 'y', (0x79)
SEG_UNSUPPORTED_CHAR, // 'z', (0x7A)
SEG_B | SEG_C | SEG_G, // '{', (0x7B)
SEG_UNSUPPORTED_CHAR, // '|', (0x7C)
SEG_E | SEG_F | SEG_G, // '}', (0x7D)
SEG_UNSUPPORTED_CHAR, // '~', (0x7E)
};
void Display::setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>& pos_to_out_map) {
void Display::setup(std::vector<uint8_t> &seg_to_out_map, std::vector<uint8_t> &pos_to_out_map) {
this->default_update_interval_ = this->max6921_->get_update_interval();
this->seg_to_out_map_ = seg_to_out_map;
this->pos_to_out_map_ = pos_to_out_map;
@ -139,7 +137,7 @@ void Display::setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>&
// find smallest segment DOUT number...
this->seg_out_smallest_ = 19;
for (uint8_t i=0; i<this->seg_to_out_map_.size(); i++) {
for (uint8_t i = 0; i < this->seg_to_out_map_.size(); i++) {
if (this->seg_to_out_map_[i] < this->seg_out_smallest_)
this->seg_out_smallest_ = this->seg_to_out_map_[i];
}
@ -147,8 +145,8 @@ void Display::setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>&
// calculate refresh period for 60Hz
this->refresh_period_us_ = 1000000 / 60 / this->num_digits_;
ESP_LOGCONFIG(TAG, "Set display refresh period: %" PRIu32 "us for %u digits @ 60Hz",
this->refresh_period_us_, this->num_digits_);
ESP_LOGCONFIG(TAG, "Set display refresh period: %" PRIu32 "us for %u digits @ 60Hz", this->refresh_period_us_,
this->num_digits_);
/* Setup display refresh.
* Using a timer is not an option, because the WiFi component uses timer as
@ -156,12 +154,12 @@ void Display::setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>&
* thread on 2nd MCU core is used.
*/
xTaskCreatePinnedToCore(&Display::display_refresh_task_,
"display_refresh_task", // name
2048, // stack size
this, // pass component pointer as task parameter pv
1, // priority (one above IDLE task)
nullptr, // handle
1 // core
"display_refresh_task", // name
2048, // stack size
this, // pass component pointer as task parameter pv
1, // priority (one above IDLE task)
nullptr, // handle
1 // core
);
// ESP_LOGCONFIG(TAG, "Display mode: %u", this->mode);
@ -169,7 +167,7 @@ void Display::setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>&
}
void HOT Display::display_refresh_task_(void *pv) {
Display *display = (Display*)pv;
Display *display = (Display *) pv;
static uint count = display->num_digits_;
static uint current_pos = 1;
@ -186,15 +184,13 @@ void HOT Display::display_refresh_task_(void *pv) {
}
if (count < display->num_digits_) {
count++;
ESP_LOGVV(TAG, "%s(): SPI transfer for position %u: 0x%02x%02x%02x",
__func__, current_pos,
display->out_buf_[(current_pos-1)*3],
display->out_buf_[(current_pos-1)*3+1],
display->out_buf_[(current_pos-1)*3+2]);
ESP_LOGVV(TAG, "%s(): SPI transfer for position %u: 0x%02x%02x%02x", __func__, current_pos,
display->out_buf_[(current_pos - 1) * 3], display->out_buf_[(current_pos - 1) * 3 + 1],
display->out_buf_[(current_pos - 1) * 3 + 2]);
}
// write MAX9621 data of current display position...
display->max6921_->write_data(&display->out_buf_[(current_pos-1)*3], 3);
display->max6921_->write_data(&display->out_buf_[(current_pos - 1) * 3], 3);
// next display position...
if (++current_pos > display->num_digits_)
@ -204,12 +200,11 @@ void HOT Display::display_refresh_task_(void *pv) {
}
}
void Display::dump_config() {
char seg_name[3];
// display segment to DOUTx mapping...
for (uint i=0; i<this->seg_to_out_map_.size(); i++) {
for (uint i = 0; i < this->seg_to_out_map_.size(); i++) {
if (i < 7) {
seg_name[0] = 'a' + i;
seg_name[1] = 0;
@ -218,13 +213,12 @@ void Display::dump_config() {
ESP_LOGCONFIG(TAG, " Display segment %2s: OUT%u", seg_name, this->seg_to_out_map_[i]);
}
// display position to DOUTx mapping...
for (uint i=0; i<this->seg_to_out_map_.size(); i++) {
for (uint i = 0; i < this->seg_to_out_map_.size(); i++) {
ESP_LOGCONFIG(TAG, " Display position %2u: OUT%u", i, this->pos_to_out_map_[i]);
}
ESP_LOGCONFIG(TAG, " Brightness: %.1f", get_brightness());
}
/**
* @brief Checks if the given character activates the point segment only.
*
@ -232,17 +226,14 @@ void Display::dump_config() {
*
* @return true, if character activates the point segment only, otherwise false
*/
bool Display::isPointSegOnly(char c) {
return ((c == ',') || (c == '.'));
}
bool Display::isPointSegOnly(char c) { return ((c == ',') || (c == '.')); }
void Display::init_font__(void) {
uint8_t seg_data;
this->ascii_out_data_ = new uint8_t[ARRAY_ELEM_COUNT(ASCII_TO_SEG)]; // NOLINT
for (size_t ascii_idx=0; ascii_idx<ARRAY_ELEM_COUNT(ASCII_TO_SEG); ascii_idx++) {
for (size_t ascii_idx = 0; ascii_idx < ARRAY_ELEM_COUNT(ASCII_TO_SEG); ascii_idx++) {
this->ascii_out_data_[ascii_idx] = 0;
seg_data = progmem_read_byte(&ASCII_TO_SEG[ascii_idx]);
if (seg_data & SEG_A)
@ -271,9 +262,9 @@ void Display::init_font__(void) {
*/
void Display::clear(int pos) {
if (pos < 0)
memset(this->out_buf_, 0, this->out_buf_size_); // clear whole display buffer
memset(this->out_buf_, 0, this->out_buf_size_); // clear whole display buffer
else if (pos < this->num_digits_)
memset(&this->out_buf_[pos*3], 0, 3); // clear display buffer at given position
memset(&this->out_buf_[pos * 3], 0, 3); // clear display buffer at given position
else
ESP_LOGW(TAG, "Invalid display position %i (max=%u)", pos, this->num_digits_ - 1);
}
@ -308,17 +299,17 @@ void Display::restore_update_interval(void) {
void Display::update(void) {
// handle display brightness...
if (this->brightness_cfg_changed_) {
uint32_t inverted_duty = this->brightness_max_duty_ - \
this->brightness_max_duty_ * \
this->brightness_cfg_value_; // calc duty for low-active BLANK pin
ESP_LOGD(TAG, "Change display brightness to %.1f (off-time duty=%u/%u)",
brightness_cfg_value_, inverted_duty, this->brightness_max_duty_);
uint32_t inverted_duty =
this->brightness_max_duty_ -
this->brightness_max_duty_ * this->brightness_cfg_value_; // calc duty for low-active BLANK pin
ESP_LOGD(TAG, "Change display brightness to %.1f (off-time duty=%u/%u)", brightness_cfg_value_, inverted_duty,
this->brightness_max_duty_);
ledcWrite(this->brightness_pwm_channel_, inverted_duty);
this->brightness_cfg_changed_ = false;
}
// handle text effects...
if (this->disp_text_.effect != TEXT_EFFECT_NONE) { // any effect enabled?
if (this->disp_text_.effect != TEXT_EFFECT_NONE) { // any effect enabled?
switch (this->disp_text_.effect) {
case TEXT_EFFECT_BLINK:
update_out_buf_();
@ -332,10 +323,10 @@ void Display::update(void) {
set_mode(DISP_MODE_PRINT);
break;
}
if (this->disp_text_.effect == TEXT_EFFECT_NONE) { // effect finished?
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
set_mode(DISP_MODE_PRINT); // switch back to "it" interface
}
}
@ -352,16 +343,15 @@ void Display::update(void) {
void Display::set_demo_mode(demo_mode_t mode, uint32_t interval, uint8_t cycle_num) {
uint text_idx, font_idx;
ESP_LOGD(TAG, "Set demo mode: mode=%i, update-interval=%" PRIu32 "ms, cycle_num=%u",
mode, interval, cycle_num);
ESP_LOGD(TAG, "Set demo mode: mode=%i, update-interval=%" PRIu32 "ms, cycle_num=%u", mode, interval, cycle_num);
switch (mode) {
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?
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?
ESP_LOGD(TAG, "Font too large for internal text buffer");
break;
}
@ -381,7 +371,7 @@ void Display::set_demo_mode(demo_mode_t mode, uint32_t interval, uint8_t cycle_n
clear();
}
void Display::set_demo_mode(const std::string& mode, uint32_t interval, uint8_t cycle_num) {
void Display::set_demo_mode(const std::string &mode, uint32_t interval, uint8_t cycle_num) {
if (str_equals_case_insensitive(mode, "off")) {
this->set_demo_mode(DEMO_MODE_OFF, interval, cycle_num);
} else if (str_equals_case_insensitive(mode, "scroll_font")) {
@ -404,13 +394,12 @@ void Display::set_demo_mode(const std::string& mode, uint32_t interval, uint8_t
*
* @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, "Set text (given): text=%s, start-pos=%u, align=%s, duration=%" PRIu32 "ms, "\
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,
"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);
text.c_str(), start_pos, align.c_str(), duration, effect.c_str(), interval, cycle_num);
// store new text...
this->disp_text_.set_text(start_pos, this->num_digits_ - 1, text);
@ -427,9 +416,8 @@ int Display::set_text(const std::string& text, uint8_t start_pos, const std::str
// update display mode...
set_mode(DISP_MODE_OTHER, duration);
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_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_();
}
@ -445,7 +433,7 @@ int Display::set_text(const std::string& text, uint8_t start_pos, const std::str
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
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...
@ -464,27 +452,28 @@ int Display::set_text(const char *text, uint8_t start_pos) {
int Display::update_out_buf_(void) {
uint visible_idx_offset = 0;
for (uint pos=0; pos<this->num_digits_; pos++) {
for (uint pos = 0; pos < this->num_digits_; pos++) {
char pos_char;
uint32_t out_data;
bool bGetNextChar, bClearPos = true;
do {
// determine character for current display position...
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?
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 = 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 (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
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;
}
}
@ -495,42 +484,40 @@ int Display::update_out_buf_(void) {
clear(pos);
// create segment data...
if ((pos_char >= ' ') &&
((pos_char - ' ') < ARRAY_ELEM_COUNT(ASCII_TO_SEG))) { // supported char?
out_data = this->ascii_out_data_[pos_char - ' ']; // yes ->
if ((pos_char >= ' ') && ((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 (0x%02x): %c", pos_char, (pos_char>=0x20)?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);
#if 0
#if 0
// At the moment an unsupport character is equal to blank (' ').
// To distinguish an unsupported character from blank we would need to
// increase font data type from uint8_t to uint16_t!
if (out_data == SEG_UNSUPPORTED_CHAR) {
ESP_LOGW(TAG, "Encountered character '%c (0x%02x)' with no display representation!", *vi_text, *vi_text);
}
#endif
#endif
// shift data to the smallest segment OUT position...
out_data <<= (this->seg_out_smallest_);
ESP_LOGVV(TAG, "%s(): segment data shifted to first segment bit (OUT%u): 0x%06x",
__func__, this->seg_out_smallest_, out_data);
ESP_LOGVV(TAG, "%s(): segment data shifted to first segment bit (OUT%u): 0x%06x", __func__, this->seg_out_smallest_,
out_data);
// add position data...
out_data |= (1 << this->pos_to_out_map_[pos]);
ESP_LOGVV(TAG, "%s(): OUT data with position: 0x%06x", __func__, out_data);
// write to appropriate position of display buffer...
this->out_buf_[pos*3+0] |= (uint8_t)((out_data >> 16) & 0xFF);
this->out_buf_[pos*3+1] |= (uint8_t)((out_data >> 8) & 0xFF);
this->out_buf_[pos*3+2] |= (uint8_t)(out_data & 0xFF);
ESP_LOGVV(TAG, "%s(): display buffer of position %u: 0x%02x%02x%02x",
__func__, pos+1, this->out_buf_[pos*3+0], this->out_buf_[pos*3+1],
this->out_buf_[pos*3+2]);
this->out_buf_[pos * 3 + 0] |= (uint8_t) ((out_data >> 16) & 0xFF);
this->out_buf_[pos * 3 + 1] |= (uint8_t) ((out_data >> 8) & 0xFF);
this->out_buf_[pos * 3 + 2] |= (uint8_t) (out_data & 0xFF);
ESP_LOGVV(TAG, "%s(): display buffer of position %u: 0x%02x%02x%02x", __func__, pos + 1,
this->out_buf_[pos * 3 + 0], this->out_buf_[pos * 3 + 1], 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, this->disp_text_.visible_idx, visible_idx_offset, this->disp_text_.visible_len);
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, this->disp_text_.visible_idx, visible_idx_offset, this->disp_text_.visible_len);
}
this->disp_text_.content_changed = true;
@ -561,24 +548,22 @@ DisplayText::DisplayText() {
*
* @return number of stored characters
*/
int DisplayText::set_text(uint start_pos, uint max_pos, const std::string& text) {
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");
this->start_pos = 0;
}
else
} else
this->start_pos = start_pos;
this->max_pos = max_pos;
strncpy(this->text, text.c_str(), sizeof(this->text) - 1);
this->text[sizeof(this->text)-1] = 0;
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.
*/
@ -590,10 +575,10 @@ void DisplayText::init_text_align_(void) {
this->start_pos = 0;
break;
case TEXT_ALIGN_CENTER:
this->start_pos = ((this->max_pos+1) - this->visible_len) / 2;
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;
this->start_pos = (this->max_pos + 1) - this->visible_len;
break;
}
}
@ -604,7 +589,7 @@ void DisplayText::init_text_align_(void) {
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->start_pos = this->max_pos; // start at right side
this->visible_idx = 0;
this->visible_len = 1;
break;
@ -623,16 +608,15 @@ void DisplayText::init_text_effect_(void) {
*
* @param align text align
*/
void DisplayText::set_text_align(text_align_t 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);
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);
}
/**
@ -640,8 +624,7 @@ void DisplayText::set_text_align(text_align_t align)
*
* @param align text align (as string)
*/
void DisplayText::set_text_align(const std::string& align)
{
void DisplayText::set_text_align(const std::string &align) {
text_align_t text_align = TEXT_ALIGN_LAST_ENUM;
if (!align.empty()) {
@ -653,8 +636,7 @@ void DisplayText::set_text_align(const std::string& align)
text_align = TEXT_ALIGN_RIGHT;
else
ESP_LOGW(TAG, "Invalid text align: %s", align);
}
else
} else
ESP_LOGW(TAG, "No text align given");
if (text_align >= TEXT_ALIGN_LAST_ENUM)
return;
@ -667,8 +649,7 @@ void DisplayText::set_text_align(const std::string& align)
* @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)
{
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;
@ -680,8 +661,8 @@ void DisplayText::set_text_effect(text_effect_t effect, uint8_t cycle_num)
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->text, this->effect, this->cycle_num, this->start_pos, this->max_pos, this->visible_idx,
this->visible_len);
}
}
@ -691,8 +672,7 @@ void DisplayText::set_text_effect(text_effect_t effect, uint8_t cycle_num)
* @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)
{
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()) {
@ -704,8 +684,7 @@ void DisplayText::set_text_effect(const std::string& effect, uint8_t cycle_num)
text_effect = TEXT_EFFECT_SCROLL_LEFT;
else
ESP_LOGW(TAG, "Invalid text effect: %s", effect);
}
else
} else
ESP_LOGW(TAG, "No text effect given");
if (text_effect >= TEXT_EFFECT_LAST_ENUM)
return;
@ -716,14 +695,14 @@ void DisplayText::set_text_effect(const std::string& effect, uint8_t cycle_num)
* @brief Updates the mode "blink". The display buffer must be updated before.
*/
void DisplayText::blink(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);
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->effect_change_count_ >= 2) { // one on/off phase complete?
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);
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");
@ -733,28 +712,28 @@ void DisplayText::blink(void) {
}
// update visible text...
if (this->visible_len > 0) { // "on" phase?
this->visible_len = 0; // yes -> switch to "off" phase
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
init_text_effect_(); // no -> switch to "on" phase
}
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", __func__, this->start_pos, this->visible_idx,
this->visible_len);
}
/**
* @brief Updates the mode "scroll left". The display buffer must be updated before.
*/
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);
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) {
init_text_effect_();
if (this->cycle_num > 0) {
ESP_LOGD(TAG, "Scroll cycle finished (%u left)", this->cycle_num-1);
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");
@ -764,18 +743,18 @@ void DisplayText::scroll_left(void) {
}
// 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->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
++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)
++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)
}
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", __func__, this->start_pos, this->visible_idx,
this->visible_len);
}
/**
@ -788,16 +767,16 @@ void DisplayText::scroll_left(void) {
*
* @return frequency supported by hardware (0 = no support)
*/
uint32_t DisplayBrightness::config_brightness_pwm(uint8_t pwm_pin_no, uint8_t channel,
uint8_t resolution, uint32_t freq) {
uint32_t DisplayBrightness::config_brightness_pwm(uint8_t pwm_pin_no, uint8_t channel, uint8_t resolution,
uint32_t freq) {
uint32_t freq_supported;
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
ESP_LOGD(TAG, "Prepare brightness PWM: pin=%u, channel=%u, resolution=%ubit, freq=%uHz",
pwm_pin_no, channel, resolution, freq_supported);
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 {
ESP_LOGD(TAG, "Failed to configure brightness PWM");
}
@ -823,7 +802,7 @@ void DisplayBrightness::set_brightness(float percent) {
*/
DisplayMode::DisplayMode() {
this->mode = DISP_MODE_PRINT;
this->duration_ms = 0; // endless
this->duration_ms = 0; // endless
}
/**
@ -843,12 +822,10 @@ void DisplayMode::set_mode(display_mode_t mode, uint32_t duration_ms) {
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_);
ESP_LOGD(TAG, "Set display mode: mode=%i, duration=%" PRIu32 "ms, duration-start=%" PRIu32 "ms", this->mode,
this->duration_ms, this->duration_ms_start_);
}
}
} // namespace max6921
} // namespace esphome

View file

@ -10,21 +10,16 @@ namespace max6921 {
class MAX6921Component;
#define FONT_SIZE 95
#define DISPLAY_TEXT_LEN FONT_SIZE // at least font size for demo mode "scroll font"
static const uint FONT_SIZE = 95;
static const uint DISPLAY_TEXT_LEN = FONT_SIZE; // at least font size for demo mode "scroll font"
enum display_mode_t {
DISP_MODE_PRINT, // input by it-functions
DISP_MODE_OTHER, // input by actions
DISP_MODE_PRINT, // input by it-functions
DISP_MODE_OTHER, // input by actions
DISP_MODE_LAST_ENUM
};
enum text_align_t {
TEXT_ALIGN_LEFT,
TEXT_ALIGN_CENTER,
TEXT_ALIGN_RIGHT,
TEXT_ALIGN_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
@ -39,53 +34,49 @@ enum demo_mode_t {
DEMO_MODE_SCROLL_FONT,
};
class DisplayBrightness
{
class DisplayBrightness {
public:
uint32_t config_brightness_pwm(uint8_t pwm_pin_no, uint8_t channel,
uint8_t resolution, uint32_t freq_wanted);
uint32_t config_brightness_pwm(uint8_t pwm_pin_no, uint8_t channel, uint8_t resolution, uint32_t freq_wanted);
float get_brightness(void) { return this->brightness_cfg_value_; }
void set_brightness(float percent);
protected:
float brightness_cfg_value_; // brightness in percent (0.0-1.0)
float brightness_cfg_value_; // brightness in percent (0.0-1.0)
bool brightness_cfg_changed_;
uint32_t brightness_max_duty_;
uint8_t brightness_pwm_channel_;
};
class DisplayMode
{
class DisplayMode {
public:
display_mode_t mode;
uint32_t duration_ms;
DisplayMode();
void set_mode(display_mode_t mode, uint32_t duration_ms=0);
void set_mode(display_mode_t mode, uint32_t duration_ms = 0);
protected:
uint32_t duration_ms_start_;
};
class DisplayText
{
class DisplayText {
public:
bool content_changed;
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)
uint visible_idx; // current index of start of visible part
uint visible_len; // current length of visible text
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)
uint visible_idx; // current index of start of visible part
uint visible_len; // current length of visible text
text_align_t align;
text_effect_t effect;
uint8_t cycle_num;
DisplayText();
void blink(void);
void scroll_left(void);
int set_text(uint start_pos, uint max_pos, const std::string& text);
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);
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:
int effect_change_count_;
@ -93,31 +84,29 @@ class DisplayText
void init_text_effect_(void);
};
class Display : public DisplayBrightness,
public DisplayMode
{
class Display : public DisplayBrightness, public DisplayMode {
public:
Display(MAX6921Component *max6921) { max6921_ = max6921; }
void clear(int pos=-1);
void clear(int pos = -1);
void dump_config();
bool isPointSegOnly(char c);
void restore_update_interval(void);
void setup(std::vector<uint8_t>& seg_to_out_map, std::vector<uint8_t>& pos_to_out_map);
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, uint32_t interval, uint8_t cycle_num);
void set_demo_mode(const std::string& mode, uint32_t interval, uint8_t cycle_num);
void set_demo_mode(const std::string &mode, uint32_t interval, uint8_t cycle_num);
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);
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);
void set_update_interval(uint32_t interval_ms);
void update(void);
protected:
MAX6921Component *max6921_;
std::vector<uint8_t> seg_to_out_map_; // mapping of display segments to MAX6921 OUT pins
std::vector<uint8_t> pos_to_out_map_; // mapping of display positions to MAX6921 OUT pins
uint num_digits_; // number of display positions
std::vector<uint8_t> seg_to_out_map_; // mapping of display segments to MAX6921 OUT pins
std::vector<uint8_t> pos_to_out_map_; // mapping of display positions to MAX6921 OUT pins
uint num_digits_; // number of display positions
uint8_t *ascii_out_data_;
uint8_t *out_buf_; // current MAX9621 data (3 bytes for every display position)
uint8_t *out_buf_; // current MAX9621 data (3 bytes for every display position)
size_t out_buf_size_;
uint seg_out_smallest_;
uint32_t refresh_period_us_;
@ -130,6 +119,5 @@ class Display : public DisplayBrightness,
void init_font__(void);
};
} // namespace max6921
} // namespace esphome

View file

@ -46,6 +46,8 @@ CONF_POS_12_PIN = "pos_12_pin"
CONF_TEXT = "text"
CONF_ALIGN = "align"
CONF_CYCLE_NUM = "cycle_num"
CONF_OFF = "off"
CONF_SCROLL_FONT = "scroll_font"
max6921_ns = cg.esphome_ns.namespace("max6921")
@ -59,13 +61,11 @@ SetTextAction = max6921_ns.class_("SetTextAction", automation.Action)
# optional "demo_mode" configuration
CONF_DEMO_MODE_OFF = "off"
CONF_DEMO_MODE_SCROLL_FONT = "scroll_font"
DemoMode = max6921_ns.enum("DemoMode")
DEMO_MODES = {
CONF_DEMO_MODE_OFF: DemoMode.DEMO_MODE_OFF,
CONF_DEMO_MODE_SCROLL_FONT: DemoMode.DEMO_MODE_SCROLL_FONT,
}
# DemoMode = max6921_ns.enum("DemoMode")
# DEMO_MODES = {
# CONF_OFF: DemoMode.OFF,
# CONF_SCROLL_FONT: DemoMode.SCROLL_FONT,
# }
def validate_out_pin_mapping(value):

View file

@ -12,7 +12,6 @@ namespace max6921 {
static const char *const TAG = "max6921";
float MAX6921Component::get_setup_priority() const { return setup_priority::HARDWARE; }
void MAX6921Component::setup() {
@ -25,17 +24,17 @@ void MAX6921Component::setup() {
this->spi_setup();
this->load_pin_->setup();
this->load_pin_->pin_mode(gpio::FLAG_OUTPUT);
this->disable_load_(); // disable output latch
this->disable_load_(); // disable output latch
this->display_ = new Display(this);
this->display_->setup(this->seg_to_out_map__, this->pos_to_out_map__);
// setup display brightness (PWM for BLANK pin)...
if (this->display_->config_brightness_pwm(this->blank_pin_->get_pin(), 0,
PWM_RESOLUTION, PWM_FREQ_WANTED) == 0) {
if (this->display_->config_brightness_pwm(this->blank_pin_->get_pin(), 0, PWM_RESOLUTION, PWM_FREQ_WANTED) == 0) {
ESP_LOGE(TAG, "Failed to configure PWM -> set to max. brightness");
pinMode(this->blank_pin_->get_pin(), OUTPUT);
this->disable_blank_(); // enable display (max. brightness)
this->blank_pin_->pin_mode(gpio::FLAG_OUTPUT);
this->blank_pin_->setup();
this->disable_blank_(); // enable display (max. brightness)
}
this->setup_finished = true;
@ -71,13 +70,13 @@ void HOT MAX6921Component::write_data(uint8_t *ptr, size_t length) {
static bool first_call_logged = false;
assert(length == 3);
this->disable_load_(); // set LOAD to low
memcpy(data, ptr, sizeof(data)); // make copy of data, because transfer buffer will be overwritten with SPI answer
this->disable_load_(); // set LOAD to low
memcpy(data, ptr, sizeof(data)); // make copy of data, because transfer buffer will be overwritten with SPI answer
if (!first_call_logged)
ESP_LOGVV(TAG, "SPI(%u): 0x%02x%02x%02x", length, data[0], data[1], data[2]);
first_call_logged = true;
first_call_logged = true;
this->transfer_array(data, sizeof(data));
this->enable_load_(); // set LOAD to high to update output latch
this->enable_load_(); // set LOAD to high to update output latch
}
void MAX6921Component::update() {
@ -87,15 +86,14 @@ void MAX6921Component::update() {
(*this->writer_)(*this);
}
/*
* Evaluates lambda function
* start_pos: 0..n = left..right display position
* vi_text : display text
*/
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
if (this->display_->mode != DISP_MODE_PRINT) // not in "it.print" mode?
return strlen(str); // yes -> abort
return this->display_->set_text(str, start_pos);
}

View file

@ -10,8 +10,7 @@
namespace esphome {
namespace max6921 {
#define ARRAY_ELEM_COUNT(array) (sizeof(array)/sizeof(array[0]))
#define ARRAY_ELEM_COUNT(array) (sizeof(array) / sizeof(array[0]))
class MAX6921Component;
class Display;
@ -41,20 +40,19 @@ class MAX6921Component : public PollingComponent,
protected:
GPIOPin *load_pin_{};
InternalGPIOPin *blank_pin_;
InternalGPIOPin *blank_pin_{};
bool setup_finished{false};
void disable_blank_() { digitalWrite(this->blank_pin_->get_pin(), LOW); } // display on
void disable_blank_() { this->blank_pin_->digital_write(false); } // display on
void IRAM_ATTR HOT disable_load_() { this->load_pin_->digital_write(false); }
void enable_blank_() { digitalWrite(this->blank_pin_->get_pin(), HIGH); } // display off
void enable_blank_() { this->blank_pin_->digital_write(true); } // display off
void IRAM_ATTR HOT enable_load_() { this->load_pin_->digital_write(true); }
void update_demo_mode_scroll_font_(void);
optional<max6921_writer_t> writer_{};
private:
std::vector<uint8_t> seg_to_out_map__; // mapping of display segments to MAX6921 OUT pins
std::vector<uint8_t> pos_to_out_map__; // mapping of display positions to MAX6921 OUT pins
std::vector<uint8_t> seg_to_out_map__; // mapping of display segments to MAX6921 OUT pins
std::vector<uint8_t> pos_to_out_map__; // mapping of display positions to MAX6921 OUT pins
};
} // namespace max6921
} // namespace esphome