mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 11:37:27 +01:00
Support for ST7567 display 128x64 (I2C, SPI) (#5952)
This commit is contained in:
parent
93ac765425
commit
3be97868fc
@ -316,6 +316,9 @@ esphome/components/ssd1331_base/* @kbx81
|
||||
esphome/components/ssd1331_spi/* @kbx81
|
||||
esphome/components/ssd1351_base/* @kbx81
|
||||
esphome/components/ssd1351_spi/* @kbx81
|
||||
esphome/components/st7567_base/* @latonita
|
||||
esphome/components/st7567_i2c/* @latonita
|
||||
esphome/components/st7567_spi/* @latonita
|
||||
esphome/components/st7735/* @SenexCrenshaw
|
||||
esphome/components/st7789v/* @kbx81
|
||||
esphome/components/st7920/* @marsjan155
|
||||
|
55
esphome/components/st7567_base/__init__.py
Normal file
55
esphome/components/st7567_base/__init__.py
Normal file
@ -0,0 +1,55 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import display
|
||||
from esphome.const import (
|
||||
CONF_LAMBDA,
|
||||
CONF_RESET_PIN,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@latonita"]
|
||||
|
||||
st7567_base_ns = cg.esphome_ns.namespace("st7567_base")
|
||||
ST7567 = st7567_base_ns.class_("ST7567", cg.PollingComponent, display.DisplayBuffer)
|
||||
ST7567Model = st7567_base_ns.enum("ST7567Model")
|
||||
|
||||
# todo in future: reuse following constants from const.py when they are released
|
||||
CONF_INVERT_COLORS = "invert_colors"
|
||||
CONF_TRANSFORM = "transform"
|
||||
CONF_MIRROR_X = "mirror_x"
|
||||
CONF_MIRROR_Y = "mirror_y"
|
||||
|
||||
|
||||
ST7567_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend(
|
||||
{
|
||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_INVERT_COLORS, default=False): cv.boolean,
|
||||
cv.Optional(CONF_TRANSFORM): cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_MIRROR_X, default=False): cv.boolean,
|
||||
cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean,
|
||||
}
|
||||
),
|
||||
}
|
||||
).extend(cv.polling_component_schema("1s"))
|
||||
|
||||
|
||||
async def setup_st7567(var, config):
|
||||
await display.register_display(var, config)
|
||||
|
||||
if CONF_RESET_PIN in config:
|
||||
reset = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
||||
cg.add(var.set_reset_pin(reset))
|
||||
|
||||
cg.add(var.init_invert_colors(config[CONF_INVERT_COLORS]))
|
||||
|
||||
if CONF_TRANSFORM in config:
|
||||
transform = config[CONF_TRANSFORM]
|
||||
cg.add(var.init_mirror_x(transform[CONF_MIRROR_X]))
|
||||
cg.add(var.init_mirror_y(transform[CONF_MIRROR_Y]))
|
||||
|
||||
if CONF_LAMBDA in config:
|
||||
lambda_ = await cg.process_lambda(
|
||||
config[CONF_LAMBDA], [(display.DisplayRef, "it")], return_type=cg.void
|
||||
)
|
||||
cg.add(var.set_writer(lambda_))
|
152
esphome/components/st7567_base/st7567_base.cpp
Normal file
152
esphome/components/st7567_base/st7567_base.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "st7567_base.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace st7567_base {
|
||||
|
||||
static const char *const TAG = "st7567";
|
||||
|
||||
void ST7567::setup() {
|
||||
this->init_internal_(this->get_buffer_length_());
|
||||
this->display_init_();
|
||||
}
|
||||
|
||||
void ST7567::display_init_() {
|
||||
ESP_LOGD(TAG, "Initializing ST7567 display...");
|
||||
this->display_init_registers_();
|
||||
this->clear();
|
||||
this->write_display_data();
|
||||
this->command(ST7567_DISPLAY_ON);
|
||||
}
|
||||
|
||||
void ST7567::display_init_registers_() {
|
||||
this->command(ST7567_BIAS_9);
|
||||
this->command(this->mirror_x_ ? ST7567_SEG_REVERSE : ST7567_SEG_NORMAL);
|
||||
this->command(this->mirror_y_ ? ST7567_COM_NORMAL : ST7567_COM_REMAP);
|
||||
this->command(ST7567_POWER_CTL | 0x4);
|
||||
this->command(ST7567_POWER_CTL | 0x6);
|
||||
this->command(ST7567_POWER_CTL | 0x7);
|
||||
|
||||
this->set_brightness(this->brightness_);
|
||||
this->set_contrast(this->contrast_);
|
||||
|
||||
this->command(ST7567_INVERT_OFF | this->invert_colors_);
|
||||
|
||||
this->command(ST7567_BOOSTER_ON);
|
||||
this->command(ST7567_REGULATOR_ON);
|
||||
this->command(ST7567_POWER_ON);
|
||||
|
||||
this->command(ST7567_SCAN_START_LINE);
|
||||
this->command(ST7567_PIXELS_NORMAL | this->all_pixels_on_);
|
||||
}
|
||||
|
||||
void ST7567::display_sw_refresh_() {
|
||||
ESP_LOGD(TAG, "Performing refresh sequence...");
|
||||
this->command(ST7567_SW_REFRESH);
|
||||
this->display_init_registers_();
|
||||
}
|
||||
|
||||
void ST7567::request_refresh() {
|
||||
// as per datasheet: It is recommended to use the refresh sequence regularly in a specified interval.
|
||||
this->refresh_requested_ = true;
|
||||
}
|
||||
|
||||
void ST7567::update() {
|
||||
this->do_update_();
|
||||
if (this->refresh_requested_) {
|
||||
this->refresh_requested_ = false;
|
||||
this->display_sw_refresh_();
|
||||
}
|
||||
this->write_display_data();
|
||||
}
|
||||
|
||||
void ST7567::set_all_pixels_on(bool enable) {
|
||||
this->all_pixels_on_ = enable;
|
||||
this->command(ST7567_PIXELS_NORMAL | this->all_pixels_on_);
|
||||
}
|
||||
|
||||
void ST7567::set_invert_colors(bool invert_colors) {
|
||||
this->invert_colors_ = invert_colors;
|
||||
this->command(ST7567_INVERT_OFF | this->invert_colors_);
|
||||
}
|
||||
|
||||
void ST7567::set_contrast(uint8_t val) {
|
||||
this->contrast_ = val & 0b111111;
|
||||
// 0..63, 26 is normal
|
||||
|
||||
// two byte command
|
||||
// first byte 0x81
|
||||
// second byte 0-63
|
||||
|
||||
this->command(ST7567_SET_EV_CMD);
|
||||
this->command(this->contrast_);
|
||||
}
|
||||
|
||||
void ST7567::set_brightness(uint8_t val) {
|
||||
this->brightness_ = val & 0b111;
|
||||
// 0..7, 5 normal
|
||||
|
||||
//********Adjust display brightness********
|
||||
// 0x20-0x27 is the internal Rb/Ra resistance
|
||||
// adjustment setting of V5 voltage RR=4.5V
|
||||
|
||||
this->command(ST7567_RESISTOR_RATIO | this->brightness_);
|
||||
}
|
||||
|
||||
bool ST7567::is_on() { return this->is_on_; }
|
||||
|
||||
void ST7567::turn_on() {
|
||||
this->command(ST7567_DISPLAY_ON);
|
||||
this->is_on_ = true;
|
||||
}
|
||||
|
||||
void ST7567::turn_off() {
|
||||
this->command(ST7567_DISPLAY_OFF);
|
||||
this->is_on_ = false;
|
||||
}
|
||||
|
||||
void ST7567::set_scroll(uint8_t line) { this->start_line_ = line % this->get_height_internal(); }
|
||||
|
||||
int ST7567::get_width_internal() { return 128; }
|
||||
|
||||
int ST7567::get_height_internal() { return 64; }
|
||||
|
||||
// 128x64, but memory size 132x64, line starts from 0, but if mirrored then it starts from 131, not 127
|
||||
size_t ST7567::get_buffer_length_() {
|
||||
return size_t(this->get_width_internal() + 4) * size_t(this->get_height_internal()) / 8u;
|
||||
}
|
||||
|
||||
void HOT ST7567::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t pos = x + (y / 8) * this->get_width_internal();
|
||||
uint8_t subpos = y & 0x07;
|
||||
if (color.is_on()) {
|
||||
this->buffer_[pos] |= (1 << subpos);
|
||||
} else {
|
||||
this->buffer_[pos] &= ~(1 << subpos);
|
||||
}
|
||||
}
|
||||
|
||||
void ST7567::fill(Color color) { memset(buffer_, color.is_on() ? 0xFF : 0x00, this->get_buffer_length_()); }
|
||||
|
||||
void ST7567::init_reset_() {
|
||||
if (this->reset_pin_ != nullptr) {
|
||||
this->reset_pin_->setup();
|
||||
this->reset_pin_->digital_write(true);
|
||||
delay(1);
|
||||
// Trigger Reset
|
||||
this->reset_pin_->digital_write(false);
|
||||
delay(10);
|
||||
// Wake up
|
||||
this->reset_pin_->digital_write(true);
|
||||
}
|
||||
}
|
||||
|
||||
const char *ST7567::model_str_() { return "ST7567 128x64"; }
|
||||
|
||||
} // namespace st7567_base
|
||||
} // namespace esphome
|
100
esphome/components/st7567_base/st7567_base.h
Normal file
100
esphome/components/st7567_base/st7567_base.h
Normal file
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/components/display/display_buffer.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace st7567_base {
|
||||
|
||||
static const uint8_t ST7567_BOOSTER_ON = 0x2C; // internal power supply on
|
||||
static const uint8_t ST7567_REGULATOR_ON = 0x2E; // internal power supply on
|
||||
static const uint8_t ST7567_POWER_ON = 0x2F; // internal power supply on
|
||||
|
||||
static const uint8_t ST7567_DISPLAY_ON = 0xAF; // Display ON. Normal Display Mode.
|
||||
static const uint8_t ST7567_DISPLAY_OFF = 0xAE; // Display OFF. All SEGs/COMs output with VSS
|
||||
static const uint8_t ST7567_SET_START_LINE = 0x40;
|
||||
static const uint8_t ST7567_POWER_CTL = 0x28;
|
||||
static const uint8_t ST7567_SEG_NORMAL = 0xA0; //
|
||||
static const uint8_t ST7567_SEG_REVERSE = 0xA1; // mirror X axis (horizontal)
|
||||
static const uint8_t ST7567_COM_NORMAL = 0xC0; //
|
||||
static const uint8_t ST7567_COM_REMAP = 0xC8; // mirror Y axis (vertical)
|
||||
static const uint8_t ST7567_PIXELS_NORMAL = 0xA4; // display ram content
|
||||
static const uint8_t ST7567_PIXELS_ALL_ON = 0xA5; // all pixels on
|
||||
static const uint8_t ST7567_INVERT_OFF = 0xA6; // normal pixels
|
||||
static const uint8_t ST7567_INVERT_ON = 0xA7; // inverted pixels
|
||||
static const uint8_t ST7567_SCAN_START_LINE = 0x40; // scrolling = 0x40 + (0..63)
|
||||
static const uint8_t ST7567_COL_ADDR_H = 0x10; // x pos (0..95) 4 MSB
|
||||
static const uint8_t ST7567_COL_ADDR_L = 0x00; // x pos (0..95) 4 LSB
|
||||
static const uint8_t ST7567_PAGE_ADDR = 0xB0; // y pos, 8.5 rows (0..8)
|
||||
static const uint8_t ST7567_BIAS_9 = 0xA2;
|
||||
static const uint8_t ST7567_CONTRAST = 0x80; // 0x80 + (0..31)
|
||||
static const uint8_t ST7567_SET_EV_CMD = 0x81;
|
||||
static const uint8_t ST7567_SET_EV_PARAM = 0x00;
|
||||
static const uint8_t ST7567_RESISTOR_RATIO = 0x20;
|
||||
static const uint8_t ST7567_SW_REFRESH = 0xE2;
|
||||
|
||||
class ST7567 : public display::DisplayBuffer {
|
||||
public:
|
||||
void setup() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
void init_mirror_x(bool mirror_x) { this->mirror_x_ = mirror_x; }
|
||||
void init_mirror_y(bool mirror_y) { this->mirror_y_ = mirror_y; }
|
||||
void init_invert_colors(bool invert_colors) { this->invert_colors_ = invert_colors; }
|
||||
|
||||
void set_invert_colors(bool invert_colors); // inversion of screen colors
|
||||
void set_contrast(uint8_t val); // 0..63, 27-30 normal
|
||||
void set_brightness(uint8_t val); // 0..7, 5 normal
|
||||
void set_all_pixels_on(bool enable); // turn on all pixels, this doesn't affect RAM
|
||||
void set_scroll(uint8_t line); // set display start line: for screen scrolling w/o affecting RAM
|
||||
|
||||
bool is_on();
|
||||
void turn_on();
|
||||
void turn_off();
|
||||
|
||||
void request_refresh(); // from datasheet: It is recommended to use the refresh sequence regularly in a specified
|
||||
// interval.
|
||||
|
||||
float get_setup_priority() const override { return setup_priority::PROCESSOR; }
|
||||
void fill(Color color) override;
|
||||
|
||||
display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_BINARY; }
|
||||
|
||||
protected:
|
||||
virtual void command(uint8_t value) = 0;
|
||||
virtual void write_display_data() = 0;
|
||||
|
||||
void init_reset_();
|
||||
void display_init_();
|
||||
void display_init_registers_();
|
||||
void display_sw_refresh_();
|
||||
|
||||
void draw_absolute_pixel_internal(int x, int y, Color color) override;
|
||||
|
||||
int get_height_internal() override;
|
||||
int get_width_internal() override;
|
||||
size_t get_buffer_length_();
|
||||
|
||||
int get_offset_x_() { return mirror_x_ ? 4 : 0; };
|
||||
|
||||
const char *model_str_();
|
||||
|
||||
GPIOPin *reset_pin_{nullptr};
|
||||
bool is_on_{false};
|
||||
// float contrast_{1.0};
|
||||
// float brightness_{1.0};
|
||||
uint8_t contrast_{27};
|
||||
uint8_t brightness_{5};
|
||||
bool mirror_x_{true};
|
||||
bool mirror_y_{true};
|
||||
bool invert_colors_{false};
|
||||
bool all_pixels_on_{false};
|
||||
uint8_t start_line_{0};
|
||||
bool refresh_requested_{false};
|
||||
};
|
||||
|
||||
} // namespace st7567_base
|
||||
} // namespace esphome
|
1
esphome/components/st7567_i2c/__init__.py
Normal file
1
esphome/components/st7567_i2c/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@latonita"]
|
29
esphome/components/st7567_i2c/display.py
Normal file
29
esphome/components/st7567_i2c/display.py
Normal file
@ -0,0 +1,29 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import st7567_base, i2c
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES
|
||||
|
||||
CODEOWNERS = ["@latonita"]
|
||||
|
||||
AUTO_LOAD = ["st7567_base"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
st7567_i2c = cg.esphome_ns.namespace("st7567_i2c")
|
||||
I2CST7567 = st7567_i2c.class_("I2CST7567", st7567_base.ST7567, i2c.I2CDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
st7567_base.ST7567_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(I2CST7567),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x3F)),
|
||||
cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await st7567_base.setup_st7567(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
60
esphome/components/st7567_i2c/st7567_i2c.cpp
Normal file
60
esphome/components/st7567_i2c/st7567_i2c.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "st7567_i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace st7567_i2c {
|
||||
|
||||
static const char *const TAG = "st7567_i2c";
|
||||
|
||||
void I2CST7567::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up I2C ST7567 display...");
|
||||
this->init_reset_();
|
||||
|
||||
auto err = this->write(nullptr, 0);
|
||||
if (err != i2c::ERROR_OK) {
|
||||
this->error_code_ = COMMUNICATION_FAILED;
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
ST7567::setup();
|
||||
}
|
||||
|
||||
void I2CST7567::dump_config() {
|
||||
LOG_DISPLAY("", "I2CST7567", this);
|
||||
LOG_I2C_DEVICE(this);
|
||||
ESP_LOGCONFIG(TAG, " Model: %s", this->model_str_());
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Mirror X: %s", YESNO(this->mirror_x_));
|
||||
ESP_LOGCONFIG(TAG, " Mirror Y: %s", YESNO(this->mirror_y_));
|
||||
ESP_LOGCONFIG(TAG, " Invert Colors: %s", YESNO(this->invert_colors_));
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
|
||||
if (this->error_code_ == COMMUNICATION_FAILED) {
|
||||
ESP_LOGE(TAG, "Communication with I2C ST7567 failed!");
|
||||
}
|
||||
}
|
||||
|
||||
void I2CST7567::command(uint8_t value) { this->write_byte(0x00, value); }
|
||||
|
||||
void HOT I2CST7567::write_display_data() {
|
||||
// ST7567A has built-in RAM with 132x65 bit capacity which stores the display data.
|
||||
// but only first 128 pixels from each line are shown on screen
|
||||
// if screen got flipped horizontally then it shows last 128 pixels,
|
||||
// so we need to write x coordinate starting from column 4, not column 0
|
||||
this->command(esphome::st7567_base::ST7567_SET_START_LINE + this->start_line_);
|
||||
for (uint8_t y = 0; y < (uint8_t) this->get_height_internal() / 8; y++) {
|
||||
this->command(esphome::st7567_base::ST7567_PAGE_ADDR + y); // Set Page
|
||||
this->command(esphome::st7567_base::ST7567_COL_ADDR_H); // Set MSB Column address
|
||||
this->command(esphome::st7567_base::ST7567_COL_ADDR_L + this->get_offset_x_()); // Set LSB Column address
|
||||
|
||||
static const size_t BLOCK_SIZE = 64;
|
||||
for (uint8_t x = 0; x < (uint8_t) this->get_width_internal(); x += BLOCK_SIZE) {
|
||||
this->write_register(esphome::st7567_base::ST7567_SET_START_LINE, &buffer_[y * this->get_width_internal() + x],
|
||||
this->get_width_internal() - x > BLOCK_SIZE ? BLOCK_SIZE : this->get_width_internal() - x,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace st7567_i2c
|
||||
} // namespace esphome
|
23
esphome/components/st7567_i2c/st7567_i2c.h
Normal file
23
esphome/components/st7567_i2c/st7567_i2c.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/st7567_base/st7567_base.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace st7567_i2c {
|
||||
|
||||
class I2CST7567 : public st7567_base::ST7567, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
void command(uint8_t value) override;
|
||||
void write_display_data() override;
|
||||
|
||||
enum ErrorCode { NONE = 0, COMMUNICATION_FAILED } error_code_{NONE};
|
||||
};
|
||||
|
||||
} // namespace st7567_i2c
|
||||
} // namespace esphome
|
1
esphome/components/st7567_spi/__init__.py
Normal file
1
esphome/components/st7567_spi/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@latonita"]
|
34
esphome/components/st7567_spi/display.py
Normal file
34
esphome/components/st7567_spi/display.py
Normal file
@ -0,0 +1,34 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import spi, st7567_base
|
||||
from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES
|
||||
|
||||
CODEOWNERS = ["@latonita"]
|
||||
|
||||
AUTO_LOAD = ["st7567_base"]
|
||||
DEPENDENCIES = ["spi"]
|
||||
|
||||
st7567_spi = cg.esphome_ns.namespace("st7567_spi")
|
||||
SPIST7567 = st7567_spi.class_("SPIST7567", st7567_base.ST7567, spi.SPIDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
st7567_base.ST7567_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(SPIST7567),
|
||||
cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(spi.spi_device_schema()),
|
||||
cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await st7567_base.setup_st7567(var, config)
|
||||
await spi.register_spi_device(var, config)
|
||||
|
||||
dc = await cg.gpio_pin_expression(config[CONF_DC_PIN])
|
||||
cg.add(var.set_dc_pin(dc))
|
66
esphome/components/st7567_spi/st7567_spi.cpp
Normal file
66
esphome/components/st7567_spi/st7567_spi.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "st7567_spi.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace st7567_spi {
|
||||
|
||||
static const char *const TAG = "st7567_spi";
|
||||
|
||||
void SPIST7567::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up SPI ST7567 display...");
|
||||
this->spi_setup();
|
||||
this->dc_pin_->setup();
|
||||
if (this->cs_)
|
||||
this->cs_->setup();
|
||||
|
||||
this->init_reset_();
|
||||
ST7567::setup();
|
||||
}
|
||||
|
||||
void SPIST7567::dump_config() {
|
||||
LOG_DISPLAY("", "SPI ST7567", this);
|
||||
ESP_LOGCONFIG(TAG, " Model: %s", this->model_str_());
|
||||
LOG_PIN(" CS Pin: ", this->cs_);
|
||||
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Mirror X: %s", YESNO(this->mirror_x_));
|
||||
ESP_LOGCONFIG(TAG, " Mirror Y: %s", YESNO(this->mirror_y_));
|
||||
ESP_LOGCONFIG(TAG, " Invert Colors: %s", YESNO(this->invert_colors_));
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
void SPIST7567::command(uint8_t value) {
|
||||
if (this->cs_)
|
||||
this->cs_->digital_write(true);
|
||||
this->dc_pin_->digital_write(false);
|
||||
delay(1);
|
||||
this->enable();
|
||||
if (this->cs_)
|
||||
this->cs_->digital_write(false);
|
||||
this->write_byte(value);
|
||||
if (this->cs_)
|
||||
this->cs_->digital_write(true);
|
||||
this->disable();
|
||||
}
|
||||
|
||||
void HOT SPIST7567::write_display_data() {
|
||||
// ST7567A has built-in RAM with 132x65 bit capacity which stores the display data.
|
||||
// but only first 128 pixels from each line are shown on screen
|
||||
// if screen got flipped horizontally then it shows last 128 pixels,
|
||||
// so we need to write x coordinate starting from column 4, not column 0
|
||||
this->command(esphome::st7567_base::ST7567_SET_START_LINE + this->start_line_);
|
||||
for (uint8_t y = 0; y < (uint8_t) this->get_height_internal() / 8; y++) {
|
||||
this->dc_pin_->digital_write(false);
|
||||
this->command(esphome::st7567_base::ST7567_PAGE_ADDR + y); // Set Page
|
||||
this->command(esphome::st7567_base::ST7567_COL_ADDR_H); // Set MSB Column address
|
||||
this->command(esphome::st7567_base::ST7567_COL_ADDR_L + this->get_offset_x_()); // Set LSB Column address
|
||||
this->dc_pin_->digital_write(true);
|
||||
|
||||
this->enable();
|
||||
this->write_array(&this->buffer_[y * this->get_width_internal()], this->get_width_internal());
|
||||
this->disable();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace st7567_spi
|
||||
} // namespace esphome
|
29
esphome/components/st7567_spi/st7567_spi.h
Normal file
29
esphome/components/st7567_spi/st7567_spi.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/st7567_base/st7567_base.h"
|
||||
#include "esphome/components/spi/spi.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace st7567_spi {
|
||||
|
||||
class SPIST7567 : public st7567_base::ST7567,
|
||||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, spi::CLOCK_PHASE_TRAILING,
|
||||
spi::DATA_RATE_8MHZ> {
|
||||
public:
|
||||
void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; }
|
||||
|
||||
void setup() override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
void command(uint8_t value) override;
|
||||
|
||||
void write_display_data() override;
|
||||
|
||||
GPIOPin *dc_pin_;
|
||||
};
|
||||
|
||||
} // namespace st7567_spi
|
||||
} // namespace esphome
|
@ -3259,6 +3259,25 @@ display:
|
||||
inverted: true
|
||||
lambda: |-
|
||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||
- platform: st7567_i2c
|
||||
id: st7735_display_i2c
|
||||
address: 0x3F
|
||||
i2c_id: i2c_bus
|
||||
lambda: |-
|
||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||
- platform: st7567_spi
|
||||
id: st7735_display_spi
|
||||
cs_pin:
|
||||
allow_other_uses: true
|
||||
number: GPIO5
|
||||
dc_pin:
|
||||
allow_other_uses: true
|
||||
number: GPIO16
|
||||
reset_pin:
|
||||
allow_other_uses: true
|
||||
number: GPIO23
|
||||
lambda: |-
|
||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||
- platform: st7735
|
||||
id: st7735_display
|
||||
model: INITR_BLACKTAB
|
||||
|
Loading…
Reference in New Issue
Block a user