diff --git a/esphome/components/ssd1306_base/ssd1306_base.cpp b/esphome/components/ssd1306_base/ssd1306_base.cpp index e0e7f94ce0..af498aae6c 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.cpp +++ b/esphome/components/ssd1306_base/ssd1306_base.cpp @@ -1,6 +1,7 @@ #include "ssd1306_base.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome { namespace ssd1306_base { @@ -40,6 +41,64 @@ static const uint8_t SSD1305_COMMAND_SET_AREA_COLOR = 0xD8; static const uint8_t SH1107_COMMAND_SET_START_LINE = 0xDC; static const uint8_t SH1107_COMMAND_CHARGE_PUMP = 0xAD; +// Verify SSD1306Model enum is sequential 0-13 so we can use it as a table index +static_assert(SSD1306_MODEL_128_32 == 0, "SSD1306Model enum values must match table indices"); +static_assert(SSD1306_MODEL_128_64 == 1, "SSD1306Model enum values must match table indices"); +static_assert(SSD1306_MODEL_96_16 == 2, "SSD1306Model enum values must match table indices"); +static_assert(SSD1306_MODEL_64_48 == 3, "SSD1306Model enum values must match table indices"); +static_assert(SSD1306_MODEL_64_32 == 4, "SSD1306Model enum values must match table indices"); +static_assert(SSD1306_MODEL_72_40 == 5, "SSD1306Model enum values must match table indices"); +static_assert(SH1106_MODEL_128_32 == 6, "SSD1306Model enum values must match table indices"); +static_assert(SH1106_MODEL_128_64 == 7, "SSD1306Model enum values must match table indices"); +static_assert(SH1106_MODEL_96_16 == 8, "SSD1306Model enum values must match table indices"); +static_assert(SH1106_MODEL_64_48 == 9, "SSD1306Model enum values must match table indices"); +static_assert(SH1107_MODEL_128_64 == 10, "SSD1306Model enum values must match table indices"); +static_assert(SH1107_MODEL_128_128 == 11, "SSD1306Model enum values must match table indices"); +static_assert(SSD1305_MODEL_128_32 == 12, "SSD1306Model enum values must match table indices"); +static_assert(SSD1305_MODEL_128_64 == 13, "SSD1306Model enum values must match table indices"); + +// PROGMEM lookup table indexed by SSD1306Model enum (width, height per model) +struct ModelDimensions { + uint8_t width; + uint8_t height; +}; +static const ModelDimensions MODEL_DIMS[] PROGMEM = { + {128, 32}, // SSD1306_MODEL_128_32 + {128, 64}, // SSD1306_MODEL_128_64 + {96, 16}, // SSD1306_MODEL_96_16 + {64, 48}, // SSD1306_MODEL_64_48 + {64, 32}, // SSD1306_MODEL_64_32 + {72, 40}, // SSD1306_MODEL_72_40 + {128, 32}, // SH1106_MODEL_128_32 + {128, 64}, // SH1106_MODEL_128_64 + {96, 16}, // SH1106_MODEL_96_16 + {64, 48}, // SH1106_MODEL_64_48 + {64, 128}, // SH1107_MODEL_128_64 (note: width is 64, height is 128) + {128, 128}, // SH1107_MODEL_128_128 + {128, 32}, // SSD1305_MODEL_128_32 + {128, 64}, // SSD1305_MODEL_128_64 +}; + +// clang-format off +PROGMEM_STRING_TABLE(ModelStrings, + "SSD1306 128x32", // SSD1306_MODEL_128_32 + "SSD1306 128x64", // SSD1306_MODEL_128_64 + "SSD1306 96x16", // SSD1306_MODEL_96_16 + "SSD1306 64x48", // SSD1306_MODEL_64_48 + "SSD1306 64x32", // SSD1306_MODEL_64_32 + "SSD1306 72x40", // SSD1306_MODEL_72_40 + "SH1106 128x32", // SH1106_MODEL_128_32 + "SH1106 128x64", // SH1106_MODEL_128_64 + "SH1106 96x16", // SH1106_MODEL_96_16 + "SH1106 64x48", // SH1106_MODEL_64_48 + "SH1107 128x64", // SH1107_MODEL_128_64 + "SH1107 128x128", // SH1107_MODEL_128_128 + "SSD1305 128x32", // SSD1305_MODEL_128_32 + "SSD1305 128x64", // SSD1305_MODEL_128_64 + "Unknown" // fallback +); +// clang-format on + void SSD1306::setup() { this->init_internal_(this->get_buffer_length_()); @@ -273,56 +332,8 @@ void SSD1306::turn_off() { this->command(SSD1306_COMMAND_DISPLAY_OFF); this->is_on_ = false; } -int SSD1306::get_height_internal() { - switch (this->model_) { - case SH1107_MODEL_128_64: - case SH1107_MODEL_128_128: - return 128; - case SSD1306_MODEL_128_32: - case SSD1306_MODEL_64_32: - case SH1106_MODEL_128_32: - case SSD1305_MODEL_128_32: - return 32; - case SSD1306_MODEL_128_64: - case SH1106_MODEL_128_64: - case SSD1305_MODEL_128_64: - return 64; - case SSD1306_MODEL_96_16: - case SH1106_MODEL_96_16: - return 16; - case SSD1306_MODEL_64_48: - case SH1106_MODEL_64_48: - return 48; - case SSD1306_MODEL_72_40: - return 40; - default: - return 0; - } -} -int SSD1306::get_width_internal() { - switch (this->model_) { - case SSD1306_MODEL_128_32: - case SH1106_MODEL_128_32: - case SSD1306_MODEL_128_64: - case SH1106_MODEL_128_64: - case SSD1305_MODEL_128_32: - case SSD1305_MODEL_128_64: - case SH1107_MODEL_128_128: - return 128; - case SSD1306_MODEL_96_16: - case SH1106_MODEL_96_16: - return 96; - case SSD1306_MODEL_64_48: - case SSD1306_MODEL_64_32: - case SH1106_MODEL_64_48: - case SH1107_MODEL_128_64: - return 64; - case SSD1306_MODEL_72_40: - return 72; - default: - return 0; - } -} +int SSD1306::get_height_internal() { return progmem_read_byte(&MODEL_DIMS[this->model_].height); } +int SSD1306::get_width_internal() { return progmem_read_byte(&MODEL_DIMS[this->model_].width); } size_t SSD1306::get_buffer_length_() { return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 8u; } @@ -361,37 +372,8 @@ void SSD1306::init_reset_() { this->reset_pin_->digital_write(true); } } -const char *SSD1306::model_str_() { - switch (this->model_) { - case SSD1306_MODEL_128_32: - return "SSD1306 128x32"; - case SSD1306_MODEL_128_64: - return "SSD1306 128x64"; - case SSD1306_MODEL_64_32: - return "SSD1306 64x32"; - case SSD1306_MODEL_96_16: - return "SSD1306 96x16"; - case SSD1306_MODEL_64_48: - return "SSD1306 64x48"; - case SSD1306_MODEL_72_40: - return "SSD1306 72x40"; - case SH1106_MODEL_128_32: - return "SH1106 128x32"; - case SH1106_MODEL_128_64: - return "SH1106 128x64"; - case SH1106_MODEL_96_16: - return "SH1106 96x16"; - case SH1106_MODEL_64_48: - return "SH1106 64x48"; - case SH1107_MODEL_128_64: - return "SH1107 128x64"; - case SSD1305_MODEL_128_32: - return "SSD1305 128x32"; - case SSD1305_MODEL_128_64: - return "SSD1305 128x64"; - default: - return "Unknown"; - } +const LogString *SSD1306::model_str_() { + return ModelStrings::get_log_str(static_cast(this->model_), ModelStrings::LAST_INDEX); } } // namespace ssd1306_base diff --git a/esphome/components/ssd1306_base/ssd1306_base.h b/esphome/components/ssd1306_base/ssd1306_base.h index a573437386..61cd7fc4cc 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.h +++ b/esphome/components/ssd1306_base/ssd1306_base.h @@ -5,6 +5,9 @@ #include "esphome/components/display/display_buffer.h" namespace esphome { + +struct LogString; + namespace ssd1306_base { enum SSD1306Model { @@ -70,7 +73,7 @@ class SSD1306 : public display::DisplayBuffer { int get_height_internal() override; int get_width_internal() override; size_t get_buffer_length_(); - const char *model_str_(); + const LogString *model_str_(); SSD1306Model model_{SSD1306_MODEL_128_64}; GPIOPin *reset_pin_{nullptr}; diff --git a/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp b/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp index 47a21a8ff4..e1f6e91243 100644 --- a/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +++ b/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp @@ -28,7 +28,7 @@ void I2CSSD1306::dump_config() { " Offset X: %d\n" " Offset Y: %d\n" " Inverted Color: %s", - this->model_str_(), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), + LOG_STR_ARG(this->model_str_()), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), this->offset_x_, this->offset_y_, YESNO(this->invert_)); LOG_I2C_DEVICE(this); LOG_PIN(" Reset Pin: ", this->reset_pin_); diff --git a/esphome/components/ssd1306_spi/ssd1306_spi.cpp b/esphome/components/ssd1306_spi/ssd1306_spi.cpp index db28dfc564..af9a17c8ab 100644 --- a/esphome/components/ssd1306_spi/ssd1306_spi.cpp +++ b/esphome/components/ssd1306_spi/ssd1306_spi.cpp @@ -24,7 +24,7 @@ void SPISSD1306::dump_config() { " Offset X: %d\n" " Offset Y: %d\n" " Inverted Color: %s", - this->model_str_(), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), + LOG_STR_ARG(this->model_str_()), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), this->offset_x_, this->offset_y_, YESNO(this->invert_)); LOG_PIN(" CS Pin: ", this->cs_); LOG_PIN(" DC Pin: ", this->dc_pin_);