mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
Add SSD1305 support to SSD1306 integration along with few new options (#1902)
* Add serveral options for SSD1306 integration * Add SSD1305 support (SSD1305 is similar to SSD1306, it seems SSD1305 has brightness and color register but does not have charge pump) * Add some description when manipulating registers * Add flip, offset and invert option to get more compatibility with various display modules * Fix typo `setup_ssd1036' -> `setup_ssd1306' * Add SSD1306 brightness validation tip * Add more description, limit offset range * Changes according to linter * Fix test * Raise error instead of using warning * Fix wrong logic * Remove logger Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Remove logging import Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
8bebf138ee
commit
66761ff340
8 changed files with 159 additions and 27 deletions
|
@ -8,12 +8,19 @@ from esphome.const import (
|
|||
CONF_MODEL,
|
||||
CONF_RESET_PIN,
|
||||
CONF_BRIGHTNESS,
|
||||
CONF_CONTRAST,
|
||||
CONF_INVERT,
|
||||
)
|
||||
|
||||
ssd1306_base_ns = cg.esphome_ns.namespace("ssd1306_base")
|
||||
SSD1306 = ssd1306_base_ns.class_("SSD1306", cg.PollingComponent, display.DisplayBuffer)
|
||||
SSD1306Model = ssd1306_base_ns.enum("SSD1306Model")
|
||||
|
||||
CONF_FLIP_X = "flip_x"
|
||||
CONF_FLIP_Y = "flip_y"
|
||||
CONF_OFFSET_X = "offset_x"
|
||||
CONF_OFFSET_Y = "offset_y"
|
||||
|
||||
MODELS = {
|
||||
"SSD1306_128X32": SSD1306Model.SSD1306_MODEL_128_32,
|
||||
"SSD1306_128X64": SSD1306Model.SSD1306_MODEL_128_64,
|
||||
|
@ -23,21 +30,44 @@ MODELS = {
|
|||
"SH1106_128X64": SSD1306Model.SH1106_MODEL_128_64,
|
||||
"SH1106_96X16": SSD1306Model.SH1106_MODEL_96_16,
|
||||
"SH1106_64X48": SSD1306Model.SH1106_MODEL_64_48,
|
||||
"SSD1305_128X32": SSD1306Model.SSD1305_MODEL_128_32,
|
||||
"SSD1305_128X64": SSD1306Model.SSD1305_MODEL_128_64,
|
||||
}
|
||||
|
||||
SSD1306_MODEL = cv.enum(MODELS, upper=True, space="_")
|
||||
|
||||
|
||||
def _validate(value):
|
||||
model = value[CONF_MODEL]
|
||||
if model not in ("SSD1305_128X32", "SSD1305_128X64"):
|
||||
# Contrast is default value (1.0) while brightness is not
|
||||
# Indicates user is using old `brightness` option
|
||||
if value[CONF_BRIGHTNESS] != 1.0 and value[CONF_CONTRAST] == 1.0:
|
||||
raise cv.Invalid(
|
||||
"SSD1306/SH1106 no longer accepts brightness option, "
|
||||
'please use "contrast" instead.'
|
||||
)
|
||||
|
||||
return value
|
||||
|
||||
|
||||
SSD1306_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend(
|
||||
{
|
||||
cv.Required(CONF_MODEL): SSD1306_MODEL,
|
||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage,
|
||||
cv.Optional(CONF_CONTRAST, default=1.0): cv.percentage,
|
||||
cv.Optional(CONF_EXTERNAL_VCC): cv.boolean,
|
||||
cv.Optional(CONF_FLIP_X, default=True): cv.boolean,
|
||||
cv.Optional(CONF_FLIP_Y, default=True): cv.boolean,
|
||||
cv.Optional(CONF_OFFSET_X, default=0): cv.int_range(min=0, max=15),
|
||||
cv.Optional(CONF_OFFSET_Y, default=0): cv.int_range(min=0, max=15),
|
||||
cv.Optional(CONF_INVERT, default=False): cv.boolean,
|
||||
}
|
||||
).extend(cv.polling_component_schema("1s"))
|
||||
|
||||
|
||||
async def setup_ssd1036(var, config):
|
||||
async def setup_ssd1306(var, config):
|
||||
await cg.register_component(var, config)
|
||||
await display.register_display(var, config)
|
||||
|
||||
|
@ -47,8 +77,20 @@ async def setup_ssd1036(var, config):
|
|||
cg.add(var.set_reset_pin(reset))
|
||||
if CONF_BRIGHTNESS in config:
|
||||
cg.add(var.init_brightness(config[CONF_BRIGHTNESS]))
|
||||
if CONF_CONTRAST in config:
|
||||
cg.add(var.init_contrast(config[CONF_CONTRAST]))
|
||||
if CONF_EXTERNAL_VCC in config:
|
||||
cg.add(var.set_external_vcc(config[CONF_EXTERNAL_VCC]))
|
||||
if CONF_FLIP_X in config:
|
||||
cg.add(var.init_flip_x(config[CONF_FLIP_X]))
|
||||
if CONF_FLIP_Y in config:
|
||||
cg.add(var.init_flip_y(config[CONF_FLIP_X]))
|
||||
if CONF_OFFSET_X in config:
|
||||
cg.add(var.init_offset_x(config[CONF_OFFSET_X]))
|
||||
if CONF_OFFSET_Y in config:
|
||||
cg.add(var.init_offset_y(config[CONF_OFFSET_Y]))
|
||||
if CONF_INVERT in config:
|
||||
cg.add(var.init_invert(config[CONF_INVERT]))
|
||||
if CONF_LAMBDA in config:
|
||||
lambda_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void
|
||||
|
|
|
@ -8,12 +8,13 @@ namespace ssd1306_base {
|
|||
static const char *const TAG = "ssd1306";
|
||||
|
||||
static const uint8_t SSD1306_MAX_CONTRAST = 255;
|
||||
static const uint8_t SSD1305_MAX_BRIGHTNESS = 255;
|
||||
|
||||
static const uint8_t SSD1306_COMMAND_DISPLAY_OFF = 0xAE;
|
||||
static const uint8_t SSD1306_COMMAND_DISPLAY_ON = 0xAF;
|
||||
static const uint8_t SSD1306_COMMAND_SET_DISPLAY_CLOCK_DIV = 0xD5;
|
||||
static const uint8_t SSD1306_COMMAND_SET_MULTIPLEX = 0xA8;
|
||||
static const uint8_t SSD1306_COMMAND_SET_DISPLAY_OFFSET = 0xD3;
|
||||
static const uint8_t SSD1306_COMMAND_SET_DISPLAY_OFFSET_Y = 0xD3;
|
||||
static const uint8_t SSD1306_COMMAND_SET_START_LINE = 0x40;
|
||||
static const uint8_t SSD1306_COMMAND_CHARGE_PUMP = 0x8D;
|
||||
static const uint8_t SSD1306_COMMAND_MEMORY_MODE = 0x20;
|
||||
|
@ -28,33 +29,60 @@ static const uint8_t SSD1306_COMMAND_DISPLAY_ALL_ON_RESUME = 0xA4;
|
|||
static const uint8_t SSD1306_COMMAND_DEACTIVATE_SCROLL = 0x2E;
|
||||
static const uint8_t SSD1306_COMMAND_COLUMN_ADDRESS = 0x21;
|
||||
static const uint8_t SSD1306_COMMAND_PAGE_ADDRESS = 0x22;
|
||||
static const uint8_t SSD1306_COMMAND_NORMAL_DISPLAY = 0xA6;
|
||||
static const uint8_t SSD1306_COMMAND_INVERSE_DISPLAY = 0xA7;
|
||||
|
||||
static const uint8_t SSD1306_NORMAL_DISPLAY = 0xA6;
|
||||
static const uint8_t SSD1305_COMMAND_SET_BRIGHTNESS = 0x82;
|
||||
static const uint8_t SSD1305_COMMAND_SET_AREA_COLOR = 0xD8;
|
||||
|
||||
void SSD1306::setup() {
|
||||
this->init_internal_(this->get_buffer_length_());
|
||||
|
||||
// Turn off display during initialization (0xAE)
|
||||
this->command(SSD1306_COMMAND_DISPLAY_OFF);
|
||||
this->command(SSD1306_COMMAND_SET_DISPLAY_CLOCK_DIV);
|
||||
this->command(0x80); // suggested ratio
|
||||
|
||||
// Set oscillator frequency to 4'b1000 with no clock division (0xD5)
|
||||
this->command(SSD1306_COMMAND_SET_DISPLAY_CLOCK_DIV);
|
||||
// Oscillator frequency <= 4'b1000, no clock division
|
||||
this->command(0x80);
|
||||
|
||||
// Enable low power display mode for SSD1305 (0xD8)
|
||||
if (this->is_ssd1305_()) {
|
||||
this->command(SSD1305_COMMAND_SET_AREA_COLOR);
|
||||
this->command(0x05);
|
||||
}
|
||||
|
||||
// Set mux ratio to [Y pixels - 1] (0xA8)
|
||||
this->command(SSD1306_COMMAND_SET_MULTIPLEX);
|
||||
this->command(this->get_height_internal() - 1);
|
||||
|
||||
this->command(SSD1306_COMMAND_SET_DISPLAY_OFFSET);
|
||||
this->command(0x00); // no offset
|
||||
this->command(SSD1306_COMMAND_SET_START_LINE | 0x00); // start at line 0
|
||||
this->command(SSD1306_COMMAND_CHARGE_PUMP);
|
||||
if (this->external_vcc_)
|
||||
this->command(0x10);
|
||||
else
|
||||
this->command(0x14);
|
||||
// Set Y offset (0xD3)
|
||||
this->command(SSD1306_COMMAND_SET_DISPLAY_OFFSET_Y);
|
||||
this->command(0x00 + this->offset_y_);
|
||||
// Set start line at line 0 (0x40)
|
||||
this->command(SSD1306_COMMAND_SET_START_LINE | 0x00);
|
||||
|
||||
// SSD1305 does not have charge pump
|
||||
if (!this->is_ssd1305_()) {
|
||||
// Enable charge pump (0x8D)
|
||||
this->command(SSD1306_COMMAND_CHARGE_PUMP);
|
||||
if (this->external_vcc_)
|
||||
this->command(0x10);
|
||||
else
|
||||
this->command(0x14);
|
||||
}
|
||||
|
||||
// Set addressing mode to horizontal (0x20)
|
||||
this->command(SSD1306_COMMAND_MEMORY_MODE);
|
||||
this->command(0x00);
|
||||
this->command(SSD1306_COMMAND_SEGRE_MAP | 0x01);
|
||||
this->command(SSD1306_COMMAND_COM_SCAN_DEC);
|
||||
|
||||
// X flip mode (0xA0, 0xA1)
|
||||
this->command(SSD1306_COMMAND_SEGRE_MAP | this->flip_x_);
|
||||
|
||||
// Y flip mode (0xC0, 0xC8)
|
||||
this->command(SSD1306_COMMAND_COM_SCAN_INC | (this->flip_y_ << 3));
|
||||
|
||||
// Set pin configuration (0xDA)
|
||||
this->command(SSD1306_COMMAND_SET_COM_PINS);
|
||||
switch (this->model_) {
|
||||
case SSD1306_MODEL_128_32:
|
||||
|
@ -67,25 +95,37 @@ void SSD1306::setup() {
|
|||
case SH1106_MODEL_128_64:
|
||||
case SSD1306_MODEL_64_48:
|
||||
case SH1106_MODEL_64_48:
|
||||
case SSD1305_MODEL_128_32:
|
||||
case SSD1305_MODEL_128_64:
|
||||
this->command(0x12);
|
||||
break;
|
||||
}
|
||||
|
||||
// Pre-charge period (0xD9)
|
||||
this->command(SSD1306_COMMAND_SET_PRE_CHARGE);
|
||||
if (this->external_vcc_)
|
||||
this->command(0x22);
|
||||
else
|
||||
this->command(0xF1);
|
||||
|
||||
// Set V_COM (0xDB)
|
||||
this->command(SSD1306_COMMAND_SET_VCOM_DETECT);
|
||||
this->command(0x00);
|
||||
|
||||
// Display output follow RAM (0xA4)
|
||||
this->command(SSD1306_COMMAND_DISPLAY_ALL_ON_RESUME);
|
||||
this->command(SSD1306_NORMAL_DISPLAY);
|
||||
|
||||
// Inverse display mode (0xA6, 0xA7)
|
||||
this->command(SSD1306_COMMAND_NORMAL_DISPLAY | this->invert_);
|
||||
|
||||
// Disable scrolling mode (0x2E)
|
||||
this->command(SSD1306_COMMAND_DEACTIVATE_SCROLL);
|
||||
|
||||
set_brightness(this->brightness_);
|
||||
// Contrast and brighrness
|
||||
// SSD1306 does not have brightness setting
|
||||
set_contrast(this->contrast_);
|
||||
if (this->is_ssd1305_())
|
||||
set_brightness(this->brightness_);
|
||||
|
||||
this->fill(Color::BLACK); // clear display - ensures we do not see garbage at power-on
|
||||
this->display(); // ...write buffer, which actually clears the display's memory
|
||||
|
@ -101,12 +141,12 @@ void SSD1306::display() {
|
|||
this->command(SSD1306_COMMAND_COLUMN_ADDRESS);
|
||||
switch (this->model_) {
|
||||
case SSD1306_MODEL_64_48:
|
||||
this->command(0x20);
|
||||
this->command(0x20 + this->get_width_internal() - 1);
|
||||
this->command(0x20 + this->offset_x_);
|
||||
this->command(0x20 + this->offset_x_ + this->get_width_internal() - 1);
|
||||
break;
|
||||
default:
|
||||
this->command(0); // Page start address, 0
|
||||
this->command(this->get_width_internal() - 1);
|
||||
this->command(0 + this->offset_x_); // Page start address, 0
|
||||
this->command(this->get_width_internal() + this->offset_x_ - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -122,16 +162,28 @@ bool SSD1306::is_sh1106_() const {
|
|||
return this->model_ == SH1106_MODEL_96_16 || this->model_ == SH1106_MODEL_128_32 ||
|
||||
this->model_ == SH1106_MODEL_128_64;
|
||||
}
|
||||
bool SSD1306::is_ssd1305_() const {
|
||||
return this->model_ == SSD1305_MODEL_128_64 || this->model_ == SSD1305_MODEL_128_64;
|
||||
}
|
||||
void SSD1306::update() {
|
||||
this->do_update_();
|
||||
this->display();
|
||||
}
|
||||
void SSD1306::set_contrast(float contrast) {
|
||||
// validation
|
||||
this->contrast_ = clamp(contrast, 0.0F, 1.0F);
|
||||
// now write the new contrast level to the display (0x81)
|
||||
this->command(SSD1306_COMMAND_SET_CONTRAST);
|
||||
this->command(int(SSD1306_MAX_CONTRAST * (this->contrast_)));
|
||||
}
|
||||
void SSD1306::set_brightness(float brightness) {
|
||||
// validation
|
||||
if (!this->is_ssd1305_())
|
||||
return;
|
||||
this->brightness_ = clamp(brightness, 0.0F, 1.0F);
|
||||
// now write the new brightness level to the display
|
||||
this->command(SSD1306_COMMAND_SET_CONTRAST);
|
||||
this->command(int(SSD1306_MAX_CONTRAST * (this->brightness_)));
|
||||
// now write the new brightness level to the display (0x82)
|
||||
this->command(SSD1305_COMMAND_SET_BRIGHTNESS);
|
||||
this->command(int(SSD1305_MAX_BRIGHTNESS * (this->brightness_)));
|
||||
}
|
||||
bool SSD1306::is_on() { return this->is_on_; }
|
||||
void SSD1306::turn_on() {
|
||||
|
@ -146,9 +198,11 @@ int SSD1306::get_height_internal() {
|
|||
switch (this->model_) {
|
||||
case SSD1306_MODEL_128_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:
|
||||
|
@ -166,6 +220,8 @@ int SSD1306::get_width_internal() {
|
|||
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:
|
||||
return 128;
|
||||
case SSD1306_MODEL_96_16:
|
||||
case SH1106_MODEL_96_16:
|
||||
|
@ -227,6 +283,10 @@ const char *SSD1306::model_str_() {
|
|||
return "SH1106 96x16";
|
||||
case SH1106_MODEL_64_48:
|
||||
return "SH1106 64x48";
|
||||
case SSD1305_MODEL_128_32:
|
||||
return "SSD1305 128x32";
|
||||
case SSD1305_MODEL_128_64:
|
||||
return "SSD1305 128x32";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ enum SSD1306Model {
|
|||
SH1106_MODEL_128_64,
|
||||
SH1106_MODEL_96_16,
|
||||
SH1106_MODEL_64_48,
|
||||
SSD1305_MODEL_128_32,
|
||||
SSD1305_MODEL_128_64,
|
||||
};
|
||||
|
||||
class SSD1306 : public PollingComponent, public display::DisplayBuffer {
|
||||
|
@ -29,8 +31,15 @@ class SSD1306 : public PollingComponent, public display::DisplayBuffer {
|
|||
void set_model(SSD1306Model model) { this->model_ = model; }
|
||||
void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
void set_external_vcc(bool external_vcc) { this->external_vcc_ = external_vcc; }
|
||||
void init_contrast(float contrast) { this->contrast_ = contrast; }
|
||||
void set_contrast(float contrast);
|
||||
void init_brightness(float brightness) { this->brightness_ = brightness; }
|
||||
void set_brightness(float brightness);
|
||||
void init_flip_x(boolean flip_x) { this->flip_x_ = flip_x; }
|
||||
void init_flip_y(boolean flip_y) { this->flip_y_ = flip_y; }
|
||||
void init_offset_x(uint8_t offset_x) { this->offset_x_ = offset_x; }
|
||||
void init_offset_y(uint8_t offset_y) { this->offset_y_ = offset_y; }
|
||||
void init_invert(boolean invert) { this->invert_ = invert; }
|
||||
bool is_on();
|
||||
void turn_on();
|
||||
void turn_off();
|
||||
|
@ -43,6 +52,7 @@ class SSD1306 : public PollingComponent, public display::DisplayBuffer {
|
|||
void init_reset_();
|
||||
|
||||
bool is_sh1106_() const;
|
||||
bool is_ssd1305_() const;
|
||||
|
||||
void draw_absolute_pixel_internal(int x, int y, Color color) override;
|
||||
|
||||
|
@ -55,7 +65,13 @@ class SSD1306 : public PollingComponent, public display::DisplayBuffer {
|
|||
GPIOPin *reset_pin_{nullptr};
|
||||
bool external_vcc_{false};
|
||||
bool is_on_{false};
|
||||
float contrast_{1.0};
|
||||
float brightness_{1.0};
|
||||
bool flip_x_{true};
|
||||
bool flip_y_{true};
|
||||
uint8_t offset_x_{0};
|
||||
uint8_t offset_y_{0};
|
||||
bool invert_{false};
|
||||
};
|
||||
|
||||
} // namespace ssd1306_base
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import ssd1306_base, i2c
|
||||
from esphome.components.ssd1306_base import _validate
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES
|
||||
|
||||
AUTO_LOAD = ["ssd1306_base"]
|
||||
|
@ -18,10 +19,11 @@ CONFIG_SCHEMA = cv.All(
|
|||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x3C)),
|
||||
cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
|
||||
_validate,
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await ssd1306_base.setup_ssd1036(var, config)
|
||||
await ssd1306_base.setup_ssd1306(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
|
|
@ -25,6 +25,11 @@ void I2CSSD1306::dump_config() {
|
|||
ESP_LOGCONFIG(TAG, " Model: %s", this->model_str_());
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
ESP_LOGCONFIG(TAG, " External VCC: %s", YESNO(this->external_vcc_));
|
||||
ESP_LOGCONFIG(TAG, " Flip X: %s", YESNO(this->flip_x_));
|
||||
ESP_LOGCONFIG(TAG, " Flip Y: %s", YESNO(this->flip_y_));
|
||||
ESP_LOGCONFIG(TAG, " Offset X: %d", this->offset_x_);
|
||||
ESP_LOGCONFIG(TAG, " Offset Y: %d", this->offset_y_);
|
||||
ESP_LOGCONFIG(TAG, " Inverted Color: %s", YESNO(this->invert_));
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
|
||||
if (this->error_code_ == COMMUNICATION_FAILED) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import esphome.codegen as cg
|
|||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import spi, ssd1306_base
|
||||
from esphome.components.ssd1306_base import _validate
|
||||
from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES
|
||||
|
||||
AUTO_LOAD = ["ssd1306_base"]
|
||||
|
@ -20,12 +21,13 @@ CONFIG_SCHEMA = cv.All(
|
|||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(spi.spi_device_schema()),
|
||||
cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
|
||||
_validate,
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await ssd1306_base.setup_ssd1036(var, config)
|
||||
await ssd1306_base.setup_ssd1306(var, config)
|
||||
await spi.register_spi_device(var, config)
|
||||
|
||||
dc = await cg.gpio_pin_expression(config[CONF_DC_PIN])
|
||||
|
|
|
@ -22,6 +22,11 @@ void SPISSD1306::dump_config() {
|
|||
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
ESP_LOGCONFIG(TAG, " External VCC: %s", YESNO(this->external_vcc_));
|
||||
ESP_LOGCONFIG(TAG, " Flip X: %s", YESNO(this->flip_x_));
|
||||
ESP_LOGCONFIG(TAG, " Flip Y: %s", YESNO(this->flip_y_));
|
||||
ESP_LOGCONFIG(TAG, " Offset X: %d", this->offset_x_);
|
||||
ESP_LOGCONFIG(TAG, " Offset Y: %d", this->offset_y_);
|
||||
ESP_LOGCONFIG(TAG, " Inverted Color: %s", YESNO(this->invert_));
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
void SPISSD1306::command(uint8_t value) {
|
||||
|
|
|
@ -2072,7 +2072,7 @@ display:
|
|||
reset_pin: GPIO23
|
||||
address: 0x3C
|
||||
id: display1
|
||||
brightness: 60%
|
||||
contrast: 60%
|
||||
pages:
|
||||
- id: page1
|
||||
lambda: |-
|
||||
|
|
Loading…
Reference in a new issue