mirror of
https://github.com/esphome/esphome.git
synced 2025-03-15 07:08:20 +00:00
Merge branch 'dev' into vornado-ir
This commit is contained in:
commit
f57fb26ff0
@ -9,10 +9,10 @@ namespace online_image {
|
|||||||
static const char *const TAG = "online_image.decoder";
|
static const char *const TAG = "online_image.decoder";
|
||||||
|
|
||||||
bool ImageDecoder::set_size(int width, int height) {
|
bool ImageDecoder::set_size(int width, int height) {
|
||||||
bool resized = this->image_->resize_(width, height);
|
bool success = this->image_->resize_(width, height) > 0;
|
||||||
this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width;
|
this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width;
|
||||||
this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height;
|
this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height;
|
||||||
return resized;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
|
void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
|
||||||
@ -51,8 +51,9 @@ size_t DownloadBuffer::read(size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t DownloadBuffer::resize(size_t size) {
|
size_t DownloadBuffer::resize(size_t size) {
|
||||||
if (this->size_ == size) {
|
if (this->size_ >= size) {
|
||||||
return size;
|
// Avoid useless reallocations; if the buffer is big enough, don't reallocate.
|
||||||
|
return this->size_;
|
||||||
}
|
}
|
||||||
this->allocator_.deallocate(this->buffer_, this->size_);
|
this->allocator_.deallocate(this->buffer_, this->size_);
|
||||||
this->buffer_ = this->allocator_.allocate(size);
|
this->buffer_ = this->allocator_.allocate(size);
|
||||||
@ -61,6 +62,8 @@ size_t DownloadBuffer::resize(size_t size) {
|
|||||||
this->size_ = size;
|
this->size_ = size;
|
||||||
return size;
|
return size;
|
||||||
} else {
|
} else {
|
||||||
|
ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", size,
|
||||||
|
this->allocator_.get_max_free_block_size());
|
||||||
this->size_ = 0;
|
this->size_ = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
|
if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
|
||||||
ESP_LOGE(TAG, "Could not open image for decoding.");
|
ESP_LOGE(TAG, "Could not open image for decoding: %d", this->jpeg_.getLastError());
|
||||||
return DECODE_ERROR_INVALID_TYPE;
|
return DECODE_ERROR_INVALID_TYPE;
|
||||||
}
|
}
|
||||||
auto jpeg_type = this->jpeg_.getJPEGType();
|
auto jpeg_type = this->jpeg_.getJPEGType();
|
||||||
@ -73,7 +73,9 @@ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
|
|||||||
|
|
||||||
this->jpeg_.setUserPointer(this);
|
this->jpeg_.setUserPointer(this);
|
||||||
this->jpeg_.setPixelType(RGB8888);
|
this->jpeg_.setPixelType(RGB8888);
|
||||||
this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight());
|
if (!this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight())) {
|
||||||
|
return DECODE_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
if (!this->jpeg_.decode(0, 0, 0)) {
|
if (!this->jpeg_.decode(0, 0, 0)) {
|
||||||
ESP_LOGE(TAG, "Error while decoding.");
|
ESP_LOGE(TAG, "Error while decoding.");
|
||||||
this->jpeg_.close();
|
this->jpeg_.close();
|
||||||
|
@ -64,33 +64,34 @@ void OnlineImage::release() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnlineImage::resize_(int width_in, int height_in) {
|
size_t OnlineImage::resize_(int width_in, int height_in) {
|
||||||
int width = this->fixed_width_;
|
int width = this->fixed_width_;
|
||||||
int height = this->fixed_height_;
|
int height = this->fixed_height_;
|
||||||
if (this->auto_resize_()) {
|
if (this->is_auto_resize_()) {
|
||||||
width = width_in;
|
width = width_in;
|
||||||
height = height_in;
|
height = height_in;
|
||||||
if (this->width_ != width && this->height_ != height) {
|
if (this->width_ != width && this->height_ != height) {
|
||||||
this->release();
|
this->release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this->buffer_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
size_t new_size = this->get_buffer_size_(width, height);
|
size_t new_size = this->get_buffer_size_(width, height);
|
||||||
|
if (this->buffer_) {
|
||||||
|
// Buffer already allocated => no need to resize
|
||||||
|
return new_size;
|
||||||
|
}
|
||||||
ESP_LOGD(TAG, "Allocating new buffer of %zu bytes", new_size);
|
ESP_LOGD(TAG, "Allocating new buffer of %zu bytes", new_size);
|
||||||
this->buffer_ = this->allocator_.allocate(new_size);
|
this->buffer_ = this->allocator_.allocate(new_size);
|
||||||
if (this->buffer_ == nullptr) {
|
if (this->buffer_ == nullptr) {
|
||||||
ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", new_size,
|
ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", new_size,
|
||||||
this->allocator_.get_max_free_block_size());
|
this->allocator_.get_max_free_block_size());
|
||||||
this->end_connection_();
|
this->end_connection_();
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
this->buffer_width_ = width;
|
this->buffer_width_ = width;
|
||||||
this->buffer_height_ = height;
|
this->buffer_height_ = height;
|
||||||
this->width_ = width;
|
this->width_ = width;
|
||||||
ESP_LOGV(TAG, "New size: (%d, %d)", width, height);
|
ESP_LOGV(TAG, "New size: (%d, %d)", width, height);
|
||||||
return true;
|
return new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnlineImage::update() {
|
void OnlineImage::update() {
|
||||||
|
@ -99,9 +99,22 @@ class OnlineImage : public PollingComponent,
|
|||||||
|
|
||||||
int get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; }
|
int get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; }
|
||||||
|
|
||||||
ESPHOME_ALWAYS_INLINE bool auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; }
|
ESPHOME_ALWAYS_INLINE bool is_auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; }
|
||||||
|
|
||||||
bool resize_(int width, int height);
|
/**
|
||||||
|
* @brief Resize the image buffer to the requested dimensions.
|
||||||
|
*
|
||||||
|
* The buffer will be allocated if not existing.
|
||||||
|
* If the dimensions have been fixed in the yaml config, the buffer will be created
|
||||||
|
* with those dimensions and not resized, even on request.
|
||||||
|
* Otherwise, the old buffer will be deallocated and a new buffer with the requested
|
||||||
|
* allocated
|
||||||
|
*
|
||||||
|
* @param width
|
||||||
|
* @param height
|
||||||
|
* @return 0 if no memory could be allocated, the size of the new buffer otherwise.
|
||||||
|
*/
|
||||||
|
size_t resize_(int width, int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draw a pixel into the buffer.
|
* @brief Draw a pixel into the buffer.
|
||||||
|
@ -83,6 +83,12 @@ void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) {
|
|||||||
this->update_entity_row_(stream, obj, area, node, friendly_name);
|
this->update_entity_row_(stream, obj, area, node, friendly_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_VALVE
|
||||||
|
this->valve_type_(stream);
|
||||||
|
for (auto *obj : App.get_valves())
|
||||||
|
this->valve_row_(stream, obj, area, node, friendly_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
req->send(stream);
|
req->send(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -770,6 +776,54 @@ void PrometheusHandler::update_entity_row_(AsyncResponseStream *stream, update::
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_VALVE
|
||||||
|
void PrometheusHandler::valve_type_(AsyncResponseStream *stream) {
|
||||||
|
stream->print(F("#TYPE esphome_valve_operation gauge\n"));
|
||||||
|
stream->print(F("#TYPE esphome_valve_failed gauge\n"));
|
||||||
|
stream->print(F("#TYPE esphome_valve_position gauge\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrometheusHandler::valve_row_(AsyncResponseStream *stream, valve::Valve *obj, std::string &area, std::string &node,
|
||||||
|
std::string &friendly_name) {
|
||||||
|
if (obj->is_internal() && !this->include_internal_)
|
||||||
|
return;
|
||||||
|
stream->print(F("esphome_valve_failed{id=\""));
|
||||||
|
stream->print(relabel_id_(obj).c_str());
|
||||||
|
add_area_label_(stream, area);
|
||||||
|
add_node_label_(stream, node);
|
||||||
|
add_friendly_name_label_(stream, friendly_name);
|
||||||
|
stream->print(F("\",name=\""));
|
||||||
|
stream->print(relabel_name_(obj).c_str());
|
||||||
|
stream->print(F("\"} 0\n"));
|
||||||
|
// Data itself
|
||||||
|
stream->print(F("esphome_valve_operation{id=\""));
|
||||||
|
stream->print(relabel_id_(obj).c_str());
|
||||||
|
add_area_label_(stream, area);
|
||||||
|
add_node_label_(stream, node);
|
||||||
|
add_friendly_name_label_(stream, friendly_name);
|
||||||
|
stream->print(F("\",name=\""));
|
||||||
|
stream->print(relabel_name_(obj).c_str());
|
||||||
|
stream->print(F("\",operation=\""));
|
||||||
|
stream->print(valve::valve_operation_to_str(obj->current_operation));
|
||||||
|
stream->print(F("\"} "));
|
||||||
|
stream->print(F("1.0"));
|
||||||
|
stream->print(F("\n"));
|
||||||
|
// Now see if position is supported
|
||||||
|
if (obj->get_traits().get_supports_position()) {
|
||||||
|
stream->print(F("esphome_valve_position{id=\""));
|
||||||
|
stream->print(relabel_id_(obj).c_str());
|
||||||
|
add_area_label_(stream, area);
|
||||||
|
add_node_label_(stream, node);
|
||||||
|
add_friendly_name_label_(stream, friendly_name);
|
||||||
|
stream->print(F("\",name=\""));
|
||||||
|
stream->print(relabel_name_(obj).c_str());
|
||||||
|
stream->print(F("\"} "));
|
||||||
|
stream->print(obj->position);
|
||||||
|
stream->print(F("\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace prometheus
|
} // namespace prometheus
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
#endif
|
#endif
|
||||||
|
@ -161,6 +161,14 @@ class PrometheusHandler : public AsyncWebHandler, public Component {
|
|||||||
void handle_update_state_(AsyncResponseStream *stream, update::UpdateState state);
|
void handle_update_state_(AsyncResponseStream *stream, update::UpdateState state);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_VALVE
|
||||||
|
/// Return the type for prometheus
|
||||||
|
void valve_type_(AsyncResponseStream *stream);
|
||||||
|
/// Return the valve state as prometheus data point
|
||||||
|
void valve_row_(AsyncResponseStream *stream, valve::Valve *obj, std::string &area, std::string &node,
|
||||||
|
std::string &friendly_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
web_server_base::WebServerBase *base_;
|
web_server_base::WebServerBase *base_;
|
||||||
bool include_internal_{false};
|
bool include_internal_{false};
|
||||||
std::map<EntityBase *, std::string> relabel_map_id_;
|
std::map<EntityBase *, std::string> relabel_map_id_;
|
||||||
|
@ -24,6 +24,7 @@ WaveshareEPaper = waveshare_epaper_ns.class_("WaveshareEPaper", WaveshareEPaperB
|
|||||||
WaveshareEPaperBWR = waveshare_epaper_ns.class_(
|
WaveshareEPaperBWR = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaperBWR", WaveshareEPaperBase
|
"WaveshareEPaperBWR", WaveshareEPaperBase
|
||||||
)
|
)
|
||||||
|
WaveshareEPaper7C = waveshare_epaper_ns.class_("WaveshareEPaper7C", WaveshareEPaperBase)
|
||||||
WaveshareEPaperTypeA = waveshare_epaper_ns.class_(
|
WaveshareEPaperTypeA = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaperTypeA", WaveshareEPaper
|
"WaveshareEPaperTypeA", WaveshareEPaper
|
||||||
)
|
)
|
||||||
@ -52,9 +53,11 @@ WaveshareEPaper2P9InV2R2 = waveshare_epaper_ns.class_(
|
|||||||
"WaveshareEPaper2P9InV2R2", WaveshareEPaper
|
"WaveshareEPaper2P9InV2R2", WaveshareEPaper
|
||||||
)
|
)
|
||||||
GDEW029T5 = waveshare_epaper_ns.class_("GDEW029T5", WaveshareEPaper)
|
GDEW029T5 = waveshare_epaper_ns.class_("GDEW029T5", WaveshareEPaper)
|
||||||
|
GDEY029T94 = waveshare_epaper_ns.class_("GDEY029T94", WaveshareEPaper)
|
||||||
WaveshareEPaper2P9InDKE = waveshare_epaper_ns.class_(
|
WaveshareEPaper2P9InDKE = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper2P9InDKE", WaveshareEPaper
|
"WaveshareEPaper2P9InDKE", WaveshareEPaper
|
||||||
)
|
)
|
||||||
|
GDEY042T81 = waveshare_epaper_ns.class_("GDEY042T81", WaveshareEPaper)
|
||||||
WaveshareEPaper2P9InD = waveshare_epaper_ns.class_(
|
WaveshareEPaper2P9InD = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper2P9InD", WaveshareEPaper
|
"WaveshareEPaper2P9InD", WaveshareEPaper
|
||||||
)
|
)
|
||||||
@ -64,12 +67,18 @@ WaveshareEPaper4P2In = waveshare_epaper_ns.class_(
|
|||||||
WaveshareEPaper4P2InBV2 = waveshare_epaper_ns.class_(
|
WaveshareEPaper4P2InBV2 = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper4P2InBV2", WaveshareEPaper
|
"WaveshareEPaper4P2InBV2", WaveshareEPaper
|
||||||
)
|
)
|
||||||
|
WaveshareEPaper4P2InBV2BWR = waveshare_epaper_ns.class_(
|
||||||
|
"WaveshareEPaper4P2InBV2BWR", WaveshareEPaperBWR
|
||||||
|
)
|
||||||
WaveshareEPaper5P8In = waveshare_epaper_ns.class_(
|
WaveshareEPaper5P8In = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper5P8In", WaveshareEPaper
|
"WaveshareEPaper5P8In", WaveshareEPaper
|
||||||
)
|
)
|
||||||
WaveshareEPaper5P8InV2 = waveshare_epaper_ns.class_(
|
WaveshareEPaper5P8InV2 = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper5P8InV2", WaveshareEPaper
|
"WaveshareEPaper5P8InV2", WaveshareEPaper
|
||||||
)
|
)
|
||||||
|
WaveshareEPaper7P3InF = waveshare_epaper_ns.class_(
|
||||||
|
"WaveshareEPaper7P3InF", WaveshareEPaper7C
|
||||||
|
)
|
||||||
WaveshareEPaper7P5In = waveshare_epaper_ns.class_(
|
WaveshareEPaper7P5In = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper7P5In", WaveshareEPaper
|
"WaveshareEPaper7P5In", WaveshareEPaper
|
||||||
)
|
)
|
||||||
@ -91,6 +100,9 @@ WaveshareEPaper7P5InV2 = waveshare_epaper_ns.class_(
|
|||||||
WaveshareEPaper7P5InV2alt = waveshare_epaper_ns.class_(
|
WaveshareEPaper7P5InV2alt = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper7P5InV2alt", WaveshareEPaper
|
"WaveshareEPaper7P5InV2alt", WaveshareEPaper
|
||||||
)
|
)
|
||||||
|
WaveshareEPaper7P5InV2P = waveshare_epaper_ns.class_(
|
||||||
|
"WaveshareEPaper7P5InV2P", WaveshareEPaper
|
||||||
|
)
|
||||||
WaveshareEPaper7P5InHDB = waveshare_epaper_ns.class_(
|
WaveshareEPaper7P5InHDB = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper7P5InHDB", WaveshareEPaper
|
"WaveshareEPaper7P5InHDB", WaveshareEPaper
|
||||||
)
|
)
|
||||||
@ -130,13 +142,17 @@ MODELS = {
|
|||||||
"2.70inv2": ("b", WaveshareEPaper2P7InV2),
|
"2.70inv2": ("b", WaveshareEPaper2P7InV2),
|
||||||
"2.90in-b": ("b", WaveshareEPaper2P9InB),
|
"2.90in-b": ("b", WaveshareEPaper2P9InB),
|
||||||
"2.90in-bv3": ("b", WaveshareEPaper2P9InBV3),
|
"2.90in-bv3": ("b", WaveshareEPaper2P9InBV3),
|
||||||
|
"gdey029t94": ("c", GDEY029T94),
|
||||||
"2.90inv2-r2": ("c", WaveshareEPaper2P9InV2R2),
|
"2.90inv2-r2": ("c", WaveshareEPaper2P9InV2R2),
|
||||||
"2.90in-d": ("b", WaveshareEPaper2P9InD),
|
"2.90in-d": ("b", WaveshareEPaper2P9InD),
|
||||||
"2.90in-dke": ("c", WaveshareEPaper2P9InDKE),
|
"2.90in-dke": ("c", WaveshareEPaper2P9InDKE),
|
||||||
|
"gdey042t81": ("c", GDEY042T81),
|
||||||
"4.20in": ("b", WaveshareEPaper4P2In),
|
"4.20in": ("b", WaveshareEPaper4P2In),
|
||||||
"4.20in-bv2": ("b", WaveshareEPaper4P2InBV2),
|
"4.20in-bv2": ("b", WaveshareEPaper4P2InBV2),
|
||||||
|
"4.20in-bv2-bwr": ("b", WaveshareEPaper4P2InBV2BWR),
|
||||||
"5.83in": ("b", WaveshareEPaper5P8In),
|
"5.83in": ("b", WaveshareEPaper5P8In),
|
||||||
"5.83inv2": ("b", WaveshareEPaper5P8InV2),
|
"5.83inv2": ("b", WaveshareEPaper5P8InV2),
|
||||||
|
"7.30in-f": ("b", WaveshareEPaper7P3InF),
|
||||||
"7.50in": ("b", WaveshareEPaper7P5In),
|
"7.50in": ("b", WaveshareEPaper7P5In),
|
||||||
"7.50in-bv2": ("b", WaveshareEPaper7P5InBV2),
|
"7.50in-bv2": ("b", WaveshareEPaper7P5InBV2),
|
||||||
"7.50in-bv3": ("b", WaveshareEPaper7P5InBV3),
|
"7.50in-bv3": ("b", WaveshareEPaper7P5InBV3),
|
||||||
@ -144,6 +160,7 @@ MODELS = {
|
|||||||
"7.50in-bc": ("b", WaveshareEPaper7P5InBC),
|
"7.50in-bc": ("b", WaveshareEPaper7P5InBC),
|
||||||
"7.50inv2": ("b", WaveshareEPaper7P5InV2),
|
"7.50inv2": ("b", WaveshareEPaper7P5InV2),
|
||||||
"7.50inv2alt": ("b", WaveshareEPaper7P5InV2alt),
|
"7.50inv2alt": ("b", WaveshareEPaper7P5InV2alt),
|
||||||
|
"7.50inv2p": ("c", WaveshareEPaper7P5InV2P),
|
||||||
"7.50in-hd-b": ("b", WaveshareEPaper7P5InHDB),
|
"7.50in-hd-b": ("b", WaveshareEPaper7P5InHDB),
|
||||||
"2.13in-ttgo-dke": ("c", WaveshareEPaper2P13InDKE),
|
"2.13in-ttgo-dke": ("c", WaveshareEPaper2P13InDKE),
|
||||||
"2.13inv3": ("c", WaveshareEPaper2P13InV3),
|
"2.13inv3": ("c", WaveshareEPaper2P13InV3),
|
||||||
|
@ -87,7 +87,11 @@ void WaveshareEPaper2P13InV3::send_reset_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WaveshareEPaper2P13InV3::setup() {
|
void WaveshareEPaper2P13InV3::setup() {
|
||||||
setup_pins_();
|
this->init_internal_(this->get_buffer_length_());
|
||||||
|
this->setup_pins_();
|
||||||
|
this->spi_setup();
|
||||||
|
this->reset_();
|
||||||
|
|
||||||
delay(20);
|
delay(20);
|
||||||
this->send_reset_();
|
this->send_reset_();
|
||||||
// as a one-off delay this is not worth working around.
|
// as a one-off delay this is not worth working around.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace waveshare_epaper {
|
namespace waveshare_epaper {
|
||||||
@ -110,8 +111,14 @@ static const uint8_t PARTIAL_UPD_2IN9_LUT[PARTIAL_UPD_2IN9_LUT_SIZE] =
|
|||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
void WaveshareEPaperBase::setup_pins_() {
|
void WaveshareEPaperBase::setup() {
|
||||||
this->init_internal_(this->get_buffer_length_());
|
this->init_internal_(this->get_buffer_length_());
|
||||||
|
this->setup_pins_();
|
||||||
|
this->spi_setup();
|
||||||
|
this->reset_();
|
||||||
|
this->initialize();
|
||||||
|
}
|
||||||
|
void WaveshareEPaperBase::setup_pins_() {
|
||||||
this->dc_pin_->setup(); // OUTPUT
|
this->dc_pin_->setup(); // OUTPUT
|
||||||
this->dc_pin_->digital_write(false);
|
this->dc_pin_->digital_write(false);
|
||||||
if (this->reset_pin_ != nullptr) {
|
if (this->reset_pin_ != nullptr) {
|
||||||
@ -121,9 +128,6 @@ void WaveshareEPaperBase::setup_pins_() {
|
|||||||
if (this->busy_pin_ != nullptr) {
|
if (this->busy_pin_ != nullptr) {
|
||||||
this->busy_pin_->setup(); // INPUT
|
this->busy_pin_->setup(); // INPUT
|
||||||
}
|
}
|
||||||
this->spi_setup();
|
|
||||||
|
|
||||||
this->reset_();
|
|
||||||
}
|
}
|
||||||
float WaveshareEPaperBase::get_setup_priority() const { return setup_priority::PROCESSOR; }
|
float WaveshareEPaperBase::get_setup_priority() const { return setup_priority::PROCESSOR; }
|
||||||
void WaveshareEPaperBase::command(uint8_t value) {
|
void WaveshareEPaperBase::command(uint8_t value) {
|
||||||
@ -173,6 +177,87 @@ void WaveshareEPaper::fill(Color color) {
|
|||||||
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
||||||
this->buffer_[i] = fill;
|
this->buffer_[i] = fill;
|
||||||
}
|
}
|
||||||
|
void WaveshareEPaper7C::setup() {
|
||||||
|
this->init_internal_7c_(this->get_buffer_length_());
|
||||||
|
this->setup_pins_();
|
||||||
|
this->spi_setup();
|
||||||
|
this->reset_();
|
||||||
|
this->initialize();
|
||||||
|
}
|
||||||
|
void WaveshareEPaper7C::init_internal_7c_(uint32_t buffer_length) {
|
||||||
|
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||||
|
uint32_t small_buffer_length = buffer_length / NUM_BUFFERS;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_BUFFERS; i++) {
|
||||||
|
this->buffers_[i] = allocator.allocate(small_buffer_length);
|
||||||
|
if (this->buffers_[i] == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "Could not allocate buffer %d for display!", i);
|
||||||
|
for (auto &buffer : this->buffers_) {
|
||||||
|
allocator.deallocate(buffer, small_buffer_length);
|
||||||
|
buffer = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
uint8_t WaveshareEPaper7C::color_to_hex(Color color) {
|
||||||
|
uint8_t hex_code;
|
||||||
|
if (color.red > 127) {
|
||||||
|
if (color.green > 170) {
|
||||||
|
if (color.blue > 127) {
|
||||||
|
hex_code = 0x1; // White
|
||||||
|
} else {
|
||||||
|
hex_code = 0x5; // Yellow
|
||||||
|
}
|
||||||
|
} else if (color.green > 85) {
|
||||||
|
hex_code = 0x6; // Orange
|
||||||
|
} else {
|
||||||
|
hex_code = 0x4; // Red (or Magenta)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (color.green > 127) {
|
||||||
|
if (color.blue > 127) {
|
||||||
|
hex_code = 0x3; // Cyan -> Blue
|
||||||
|
} else {
|
||||||
|
hex_code = 0x2; // Green
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (color.blue > 127) {
|
||||||
|
hex_code = 0x3; // Blue
|
||||||
|
} else {
|
||||||
|
hex_code = 0x0; // Black
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex_code;
|
||||||
|
}
|
||||||
|
void WaveshareEPaper7C::fill(Color color) {
|
||||||
|
uint8_t pixel_color;
|
||||||
|
if (color.is_on()) {
|
||||||
|
pixel_color = this->color_to_hex(color);
|
||||||
|
} else {
|
||||||
|
pixel_color = 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->buffers_[0] == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "Buffer unavailable!");
|
||||||
|
} else {
|
||||||
|
uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
|
||||||
|
for (auto &buffer : this->buffers_) {
|
||||||
|
for (uint32_t buffer_pos = 0; buffer_pos < small_buffer_length; buffer_pos += 3) {
|
||||||
|
// We store 8 bitset<3> in 3 bytes
|
||||||
|
// | byte 1 | byte 2 | byte 3 |
|
||||||
|
// |aaabbbaa|abbbaaab|bbaaabbb|
|
||||||
|
buffer[buffer_pos + 0] = pixel_color << 5 | pixel_color << 2 | pixel_color >> 1;
|
||||||
|
buffer[buffer_pos + 1] = pixel_color << 7 | pixel_color << 4 | pixel_color << 1 | pixel_color >> 2;
|
||||||
|
buffer[buffer_pos + 2] = pixel_color << 6 | pixel_color << 3 | pixel_color << 0;
|
||||||
|
}
|
||||||
|
App.feed_wdt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void HOT WaveshareEPaper::draw_absolute_pixel_internal(int x, int y, Color color) {
|
void HOT WaveshareEPaper::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||||
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
|
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
|
||||||
return;
|
return;
|
||||||
@ -193,6 +278,9 @@ uint32_t WaveshareEPaper::get_buffer_length_() {
|
|||||||
uint32_t WaveshareEPaperBWR::get_buffer_length_() {
|
uint32_t WaveshareEPaperBWR::get_buffer_length_() {
|
||||||
return this->get_width_controller() * this->get_height_internal() / 4u;
|
return this->get_width_controller() * this->get_height_internal() / 4u;
|
||||||
} // black and red buffer
|
} // black and red buffer
|
||||||
|
uint32_t WaveshareEPaper7C::get_buffer_length_() {
|
||||||
|
return this->get_width_controller() * this->get_height_internal() / 8u * 3u;
|
||||||
|
} // 7 colors buffer, 1 pixel = 3 bits, we will store 8 pixels in 24 bits = 3 bytes
|
||||||
|
|
||||||
void WaveshareEPaperBWR::fill(Color color) {
|
void WaveshareEPaperBWR::fill(Color color) {
|
||||||
this->filled_rectangle(0, 0, this->get_width(), this->get_height(), color);
|
this->filled_rectangle(0, 0, this->get_width(), this->get_height(), color);
|
||||||
@ -219,7 +307,33 @@ void HOT WaveshareEPaperBWR::draw_absolute_pixel_internal(int x, int y, Color co
|
|||||||
this->buffer_[pos + buf_half_len] &= ~(0x80 >> subpos);
|
this->buffer_[pos + buf_half_len] &= ~(0x80 >> subpos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void HOT WaveshareEPaper7C::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||||
|
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t pixel_bits = this->color_to_hex(color);
|
||||||
|
uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
|
||||||
|
uint32_t pixel_position = x + y * this->get_width_controller();
|
||||||
|
uint32_t first_bit_position = pixel_position * 3;
|
||||||
|
uint32_t byte_position = first_bit_position / 8u;
|
||||||
|
uint32_t byte_subposition = first_bit_position % 8u;
|
||||||
|
uint32_t buffer_position = byte_position / small_buffer_length;
|
||||||
|
uint32_t buffer_subposition = byte_position % small_buffer_length;
|
||||||
|
|
||||||
|
if (byte_subposition <= 5) {
|
||||||
|
this->buffers_[buffer_position][buffer_subposition] =
|
||||||
|
(this->buffers_[buffer_position][buffer_subposition] & (0xFF ^ (0b111 << (5 - byte_subposition)))) |
|
||||||
|
(pixel_bits << (5 - byte_subposition));
|
||||||
|
} else {
|
||||||
|
this->buffers_[buffer_position][buffer_subposition + 0] =
|
||||||
|
(this->buffers_[buffer_position][buffer_subposition + 0] & (0xFF ^ (0b111 >> (byte_subposition - 5)))) |
|
||||||
|
(pixel_bits >> (byte_subposition - 5));
|
||||||
|
|
||||||
|
this->buffers_[buffer_position][buffer_subposition + 1] = (this->buffers_[buffer_position][buffer_subposition + 1] &
|
||||||
|
(0xFF ^ (0xFF & (0b111 << (13 - byte_subposition))))) |
|
||||||
|
(pixel_bits << (13 - byte_subposition));
|
||||||
|
}
|
||||||
|
}
|
||||||
void WaveshareEPaperBase::start_command_() {
|
void WaveshareEPaperBase::start_command_() {
|
||||||
this->dc_pin_->digital_write(false);
|
this->dc_pin_->digital_write(false);
|
||||||
this->enable();
|
this->enable();
|
||||||
@ -1677,9 +1791,82 @@ int WaveshareEPaper2P9InV2R2::get_width_controller() { return this->get_width_in
|
|||||||
void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every) {
|
void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every) {
|
||||||
this->full_update_every_ = full_update_every;
|
this->full_update_every_ = full_update_every;
|
||||||
}
|
}
|
||||||
|
// ========================================================
|
||||||
|
// Good Display 2.9in black/white
|
||||||
|
// Datasheet:
|
||||||
|
// - https://files.seeedstudio.com/wiki/Other_Display/29-epaper/GDEY029T94.pdf
|
||||||
|
// -
|
||||||
|
// https://github.com/Allen-Kuang/e-ink_Demo/blob/main/2.9%20inch%20E-paper%20-%20monocolor%20128x296/example/Display_EPD_W21.cpp
|
||||||
|
// ========================================================
|
||||||
|
|
||||||
|
void GDEY029T94::initialize() {
|
||||||
|
// EPD hardware init start
|
||||||
|
this->reset_();
|
||||||
|
|
||||||
|
this->wait_until_idle_();
|
||||||
|
this->command(0x12); // SWRESET
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
this->command(0x01); // Driver output control
|
||||||
|
this->data((this->get_height_internal() - 1) % 256);
|
||||||
|
this->data((this->get_height_internal() - 1) / 256);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
this->command(0x11); // data entry mode
|
||||||
|
this->data(0x03);
|
||||||
|
|
||||||
|
this->command(0x44); // set Ram-X address start/end position
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(this->get_width_internal() / 8 - 1);
|
||||||
|
|
||||||
|
this->command(0x45); // set Ram-Y address start/end position
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x00);
|
||||||
|
this->data((this->get_height_internal() - 1) % 256);
|
||||||
|
this->data((this->get_height_internal() - 1) / 256);
|
||||||
|
|
||||||
|
this->command(0x3C); // BorderWavefrom
|
||||||
|
this->data(0x05);
|
||||||
|
|
||||||
|
this->command(0x21); // Display update control
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x80);
|
||||||
|
|
||||||
|
this->command(0x18); // Read built-in temperature sensor
|
||||||
|
this->data(0x80);
|
||||||
|
|
||||||
|
this->command(0x4E); // set RAM x address count to 0;
|
||||||
|
this->data(0x00);
|
||||||
|
this->command(0x4F); // set RAM y address count to 0X199;
|
||||||
|
this->command(0x00);
|
||||||
|
this->command(0x00);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
}
|
||||||
|
void HOT GDEY029T94::display() {
|
||||||
|
this->command(0x24); // write RAM for black(0)/white (1)
|
||||||
|
this->start_data_();
|
||||||
|
for (uint32_t i = 0; i < this->get_buffer_length_(); i++) {
|
||||||
|
this->write_byte(this->buffer_[i]);
|
||||||
|
}
|
||||||
|
this->end_data_();
|
||||||
|
this->command(0x22); // Display Update Control
|
||||||
|
this->data(0xF7);
|
||||||
|
this->command(0x20); // Activate Display Update Sequence
|
||||||
|
this->wait_until_idle_();
|
||||||
|
}
|
||||||
|
int GDEY029T94::get_width_internal() { return 128; }
|
||||||
|
int GDEY029T94::get_height_internal() { return 296; }
|
||||||
|
void GDEY029T94::dump_config() {
|
||||||
|
LOG_DISPLAY("", "E-Paper (Good Display)", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Model: 2.9in GDEY029T94");
|
||||||
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
|
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||||
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
// ========================================================
|
// ========================================================
|
||||||
// Good Display 2.9in black/white/grey
|
// Good Display 2.9in black/white
|
||||||
// Datasheet:
|
// Datasheet:
|
||||||
// - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1680.pdf
|
// - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1680.pdf
|
||||||
// - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h
|
// - https://github.com/adafruit/Adafruit_EPD/blob/master/src/panels/ThinkInk_290_Grayscale4_T5.h
|
||||||
@ -2096,6 +2283,206 @@ void GDEW0154M09::dump_config() {
|
|||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================================================
|
||||||
|
// Good Display 4.2in black/white GDEY042T81 (SSD1683)
|
||||||
|
// Product page:
|
||||||
|
// - https://www.good-display.com/product/386.html
|
||||||
|
// Datasheet:
|
||||||
|
// - https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf
|
||||||
|
// - https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF
|
||||||
|
// Reference code from GoodDisplay:
|
||||||
|
// - https://www.good-display.com/companyfile/1572.html (2024-08-01 15:40:41)
|
||||||
|
// Other reference code:
|
||||||
|
// - https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp
|
||||||
|
// ========================================================
|
||||||
|
|
||||||
|
void GDEY042T81::initialize() {
|
||||||
|
this->init_display_();
|
||||||
|
ESP_LOGD(TAG, "Initialization complete, set the display to deep sleep");
|
||||||
|
this->deep_sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
// conflicting documentation / examples regarding reset timings
|
||||||
|
// https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF -> 10ms
|
||||||
|
// GD sample code (Display_EPD_W21.cpp, see above) -> 10 ms
|
||||||
|
// https://v4.cecdn.yun300.cn/100001_1909185148/GDEY042T81.pdf (section 14.2) -> 0.2ms (200us)
|
||||||
|
// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L351
|
||||||
|
// -> 10ms
|
||||||
|
// 10 ms seems to work, so we use this
|
||||||
|
GDEY042T81::GDEY042T81() { this->reset_duration_ = 10; }
|
||||||
|
|
||||||
|
void GDEY042T81::reset_() {
|
||||||
|
if (this->reset_pin_ != nullptr) {
|
||||||
|
this->reset_pin_->digital_write(false);
|
||||||
|
delay(reset_duration_); // NOLINT
|
||||||
|
this->reset_pin_->digital_write(true);
|
||||||
|
delay(reset_duration_); // NOLINT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDEY042T81::init_display_() {
|
||||||
|
this->reset_();
|
||||||
|
|
||||||
|
this->wait_until_idle_();
|
||||||
|
this->command(0x12); // SWRESET
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// Specify number of lines for the driver: 300 (MUX 300)
|
||||||
|
// https://v4.cecdn.yun300.cn/100001_1909185148/SSD1683.PDF (section 8.1)
|
||||||
|
// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L354
|
||||||
|
this->command(0x01); // driver output control
|
||||||
|
this->data(0x2B); // (height - 1) % 256
|
||||||
|
this->data(0x01); // (height - 1) / 256
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L360
|
||||||
|
this->command(0x3C); // BorderWaveform
|
||||||
|
this->data(0x01);
|
||||||
|
this->command(0x18); // Read built-in temperature sensor
|
||||||
|
this->data(0x80);
|
||||||
|
|
||||||
|
// GD sample code (Display_EPD_W21.cpp@90ff)
|
||||||
|
this->command(0x11); // data entry mode
|
||||||
|
this->data(0x03);
|
||||||
|
// set windows (0,0,400,300)
|
||||||
|
this->command(0x44); // set Ram-X address start/end position
|
||||||
|
this->data(0);
|
||||||
|
this->data(0x31); // (width / 8 -1)
|
||||||
|
|
||||||
|
this->command(0x45); // set Ram-y address start/end position
|
||||||
|
this->data(0);
|
||||||
|
this->data(0);
|
||||||
|
this->data(0x2B); // (height - 1) % 256
|
||||||
|
this->data(0x01); // (height - 1) / 256
|
||||||
|
|
||||||
|
// set cursor (0,0)
|
||||||
|
this->command(0x4E); // set RAM x address count to 0;
|
||||||
|
this->data(0);
|
||||||
|
this->command(0x4F); // set RAM y address count to 0;
|
||||||
|
this->data(0);
|
||||||
|
this->data(0);
|
||||||
|
|
||||||
|
this->wait_until_idle_();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L366
|
||||||
|
void GDEY042T81::update_full_() {
|
||||||
|
this->command(0x21); // display update control
|
||||||
|
this->data(0x40); // bypass RED as 0
|
||||||
|
this->data(0x00); // single chip application
|
||||||
|
|
||||||
|
// only ever do a fast update because slow updates are only relevant
|
||||||
|
// for lower operating temperatures
|
||||||
|
// see
|
||||||
|
// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_290_GDEY029T94.h#L30
|
||||||
|
//
|
||||||
|
// Should slow/fast updates be made configurable similar to how GxEPD2 does it? No idea if anyone would need it...
|
||||||
|
this->command(0x1A); // Write to temperature register
|
||||||
|
this->data(0x6E);
|
||||||
|
this->command(0x22);
|
||||||
|
this->data(0xd7);
|
||||||
|
|
||||||
|
this->command(0x20);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L389
|
||||||
|
void GDEY042T81::update_part_() {
|
||||||
|
this->command(0x21); // display update control
|
||||||
|
this->data(0x00); // RED normal
|
||||||
|
this->data(0x00); // single chip application
|
||||||
|
|
||||||
|
this->command(0x22);
|
||||||
|
this->data(0xfc);
|
||||||
|
|
||||||
|
this->command(0x20);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HOT GDEY042T81::display() {
|
||||||
|
ESP_LOGD(TAG, "Wake up the display");
|
||||||
|
this->init_display_();
|
||||||
|
|
||||||
|
if (!this->wait_until_idle_()) {
|
||||||
|
this->status_set_warning();
|
||||||
|
ESP_LOGE(TAG, "Failed to perform update, display is busy");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// basic code structure copied from WaveshareEPaper2P9InV2R2
|
||||||
|
if (this->full_update_every_ == 1) {
|
||||||
|
ESP_LOGD(TAG, "Full update");
|
||||||
|
// do single full update
|
||||||
|
this->command(0x24);
|
||||||
|
this->start_data_();
|
||||||
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
||||||
|
this->end_data_();
|
||||||
|
|
||||||
|
// TurnOnDisplay
|
||||||
|
this->update_full_();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (this->full_update_every_ == 1 ||
|
||||||
|
if (this->at_update_ == 0) {
|
||||||
|
ESP_LOGD(TAG, "Update");
|
||||||
|
// do base update
|
||||||
|
this->command(0x24);
|
||||||
|
this->start_data_();
|
||||||
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
||||||
|
this->end_data_();
|
||||||
|
|
||||||
|
this->command(0x26);
|
||||||
|
this->start_data_();
|
||||||
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
||||||
|
this->end_data_();
|
||||||
|
|
||||||
|
// TurnOnDisplay;
|
||||||
|
this->update_full_();
|
||||||
|
} else {
|
||||||
|
// do partial update (full screen)
|
||||||
|
// no need to load a LUT for GoodDisplays as they seem to have the LUT onboard
|
||||||
|
// GD example code (Display_EPD_W21.cpp@283ff)
|
||||||
|
//
|
||||||
|
// not setting the BorderWaveform here again (contrary to the GD example) because according to
|
||||||
|
// https://github.com/ZinggJM/GxEPD2/blob/03d8e7a533c1493f762e392ead12f1bcb7fab8f9/src/gdey/GxEPD2_420_GDEY042T81.cpp#L358
|
||||||
|
// it seems to be enough to set it during display initialization
|
||||||
|
ESP_LOGD(TAG, "Partial update");
|
||||||
|
this->reset_();
|
||||||
|
if (!this->wait_until_idle_()) {
|
||||||
|
this->status_set_warning();
|
||||||
|
ESP_LOGE(TAG, "Failed to perform partial update, display is busy");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->command(0x24);
|
||||||
|
this->start_data_();
|
||||||
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
||||||
|
this->end_data_();
|
||||||
|
|
||||||
|
// TurnOnDisplay
|
||||||
|
this->update_part_();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
|
||||||
|
this->wait_until_idle_();
|
||||||
|
ESP_LOGD(TAG, "Set the display back to deep sleep");
|
||||||
|
this->deep_sleep();
|
||||||
|
}
|
||||||
|
void GDEY042T81::set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; }
|
||||||
|
int GDEY042T81::get_width_internal() { return 400; }
|
||||||
|
int GDEY042T81::get_height_internal() { return 300; }
|
||||||
|
uint32_t GDEY042T81::idle_timeout_() { return 5000; }
|
||||||
|
void GDEY042T81::dump_config() {
|
||||||
|
LOG_DISPLAY("", "GoodDisplay E-Paper", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Model: 4.2in B/W GDEY042T81");
|
||||||
|
ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
|
||||||
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
|
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||||
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
static const uint8_t LUT_VCOM_DC_4_2[] = {
|
static const uint8_t LUT_VCOM_DC_4_2[] = {
|
||||||
0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
|
0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, 0x00, 0x0A, 0x01,
|
||||||
0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@ -2274,6 +2661,64 @@ void WaveshareEPaper4P2InBV2::dump_config() {
|
|||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================================================
|
||||||
|
// 4.20in Type B With Red colour support (LUT from OTP)
|
||||||
|
// Datasheet:
|
||||||
|
// - https://www.waveshare.com/w/upload/2/20/4.2inch-e-paper-module-user-manual-en.pdf
|
||||||
|
// - https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_4in2b_V2.c
|
||||||
|
// The implementation is an adaptation of WaveshareEPaper4P2InBV2 class
|
||||||
|
// ========================================================
|
||||||
|
void WaveshareEPaper4P2InBV2BWR::initialize() {
|
||||||
|
// these exact timings are required for a proper reset/init
|
||||||
|
this->reset_pin_->digital_write(false);
|
||||||
|
delay(2);
|
||||||
|
this->reset_pin_->digital_write(true);
|
||||||
|
delay(200); // NOLINT
|
||||||
|
|
||||||
|
// COMMAND POWER ON
|
||||||
|
this->command(0x04);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND PANEL SETTING
|
||||||
|
this->command(0x00);
|
||||||
|
this->data(0x0f); // LUT from OTP
|
||||||
|
}
|
||||||
|
|
||||||
|
void HOT WaveshareEPaper4P2InBV2BWR::display() {
|
||||||
|
const uint32_t buf_len = this->get_buffer_length_() / 2u;
|
||||||
|
|
||||||
|
this->command(0x10); // Send BW data Transmission
|
||||||
|
delay(2); // Delay to prevent Watchdog error
|
||||||
|
for (uint32_t i = 0; i < buf_len; ++i) {
|
||||||
|
this->data(this->buffer_[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->command(0x13); // Send red data Transmission
|
||||||
|
delay(2); // Delay to prevent Watchdog error
|
||||||
|
for (uint32_t i = 0; i < buf_len; ++i) {
|
||||||
|
// Red color need to flip bit from the buffer. Otherwise, red will conqure the screen!
|
||||||
|
this->data(~this->buffer_[buf_len + i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// COMMAND DISPLAY REFRESH
|
||||||
|
this->command(0x12);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND POWER OFF
|
||||||
|
// NOTE: power off < deep sleep
|
||||||
|
this->command(0x02);
|
||||||
|
}
|
||||||
|
int WaveshareEPaper4P2InBV2BWR::get_width_internal() { return 400; }
|
||||||
|
int WaveshareEPaper4P2InBV2BWR::get_height_internal() { return 300; }
|
||||||
|
void WaveshareEPaper4P2InBV2BWR::dump_config() {
|
||||||
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Model: 4.2in (B V2) BWR-Mode");
|
||||||
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
|
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||||
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
void WaveshareEPaper5P8In::initialize() {
|
void WaveshareEPaper5P8In::initialize() {
|
||||||
// COMMAND POWER SETTING
|
// COMMAND POWER SETTING
|
||||||
this->command(0x01);
|
this->command(0x01);
|
||||||
@ -2862,6 +3307,195 @@ void WaveshareEPaper7P5In::dump_config() {
|
|||||||
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
void WaveshareEPaper7P3InF::initialize() {
|
||||||
|
if (this->buffers_[0] == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "Buffer unavailable!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->reset_();
|
||||||
|
delay(20);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND CMDH
|
||||||
|
this->command(0xAA);
|
||||||
|
this->data(0x49);
|
||||||
|
this->data(0x55);
|
||||||
|
this->data(0x20);
|
||||||
|
this->data(0x08);
|
||||||
|
this->data(0x09);
|
||||||
|
this->data(0x18);
|
||||||
|
|
||||||
|
this->command(0x01);
|
||||||
|
this->data(0x3F);
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x32);
|
||||||
|
this->data(0x2A);
|
||||||
|
this->data(0x0E);
|
||||||
|
this->data(0x2A);
|
||||||
|
|
||||||
|
this->command(0x00);
|
||||||
|
this->data(0x5F);
|
||||||
|
this->data(0x69);
|
||||||
|
|
||||||
|
this->command(0x03);
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x54);
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x44);
|
||||||
|
|
||||||
|
this->command(0x05);
|
||||||
|
this->data(0x40);
|
||||||
|
this->data(0x1F);
|
||||||
|
this->data(0x1F);
|
||||||
|
this->data(0x2C);
|
||||||
|
|
||||||
|
this->command(0x06);
|
||||||
|
this->data(0x6F);
|
||||||
|
this->data(0x1F);
|
||||||
|
this->data(0x1F);
|
||||||
|
this->data(0x22);
|
||||||
|
|
||||||
|
this->command(0x08);
|
||||||
|
this->data(0x6F);
|
||||||
|
this->data(0x1F);
|
||||||
|
this->data(0x1F);
|
||||||
|
this->data(0x22);
|
||||||
|
|
||||||
|
// COMMAND IPC
|
||||||
|
this->command(0x13);
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x04);
|
||||||
|
|
||||||
|
this->command(0x30);
|
||||||
|
this->data(0x3C);
|
||||||
|
|
||||||
|
// COMMAND TSE
|
||||||
|
this->command(0x41);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
this->command(0x50);
|
||||||
|
this->data(0x3F);
|
||||||
|
|
||||||
|
this->command(0x60);
|
||||||
|
this->data(0x02);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
this->command(0x61);
|
||||||
|
this->data(0x03);
|
||||||
|
this->data(0x20);
|
||||||
|
this->data(0x01);
|
||||||
|
this->data(0xE0);
|
||||||
|
|
||||||
|
this->command(0x82);
|
||||||
|
this->data(0x1E);
|
||||||
|
|
||||||
|
this->command(0x84);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
// COMMAND AGID
|
||||||
|
this->command(0x86);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
this->command(0xE3);
|
||||||
|
this->data(0x2F);
|
||||||
|
|
||||||
|
// COMMAND CCSET
|
||||||
|
this->command(0xE0);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
// COMMAND TSSET
|
||||||
|
this->command(0xE6);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Display initialized successfully");
|
||||||
|
}
|
||||||
|
void HOT WaveshareEPaper7P3InF::display() {
|
||||||
|
if (this->buffers_[0] == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "Buffer unavailable!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INITIALIZATION
|
||||||
|
ESP_LOGI(TAG, "Initialise the display");
|
||||||
|
this->initialize();
|
||||||
|
|
||||||
|
// COMMAND DATA START TRANSMISSION
|
||||||
|
ESP_LOGI(TAG, "Sending data to the display");
|
||||||
|
this->command(0x10);
|
||||||
|
uint32_t small_buffer_length = this->get_buffer_length_() / NUM_BUFFERS;
|
||||||
|
uint8_t byte_to_send;
|
||||||
|
for (auto &buffer : this->buffers_) {
|
||||||
|
for (uint32_t buffer_pos = 0; buffer_pos < small_buffer_length; buffer_pos += 3) {
|
||||||
|
std::bitset<24> triplet =
|
||||||
|
buffer[buffer_pos + 0] << 16 | buffer[buffer_pos + 1] << 8 | buffer[buffer_pos + 2] << 0;
|
||||||
|
// 8 bitset<3> are stored in 3 bytes
|
||||||
|
// |aaabbbaa|abbbaaab|bbaaabbb|
|
||||||
|
// | byte 1 | byte 2 | byte 3 |
|
||||||
|
byte_to_send = ((triplet >> 17).to_ulong() & 0b01110000) | ((triplet >> 18).to_ulong() & 0b00000111);
|
||||||
|
this->data(byte_to_send);
|
||||||
|
|
||||||
|
byte_to_send = ((triplet >> 11).to_ulong() & 0b01110000) | ((triplet >> 12).to_ulong() & 0b00000111);
|
||||||
|
this->data(byte_to_send);
|
||||||
|
|
||||||
|
byte_to_send = ((triplet >> 5).to_ulong() & 0b01110000) | ((triplet >> 6).to_ulong() & 0b00000111);
|
||||||
|
this->data(byte_to_send);
|
||||||
|
|
||||||
|
byte_to_send = ((triplet << 1).to_ulong() & 0b01110000) | ((triplet << 0).to_ulong() & 0b00000111);
|
||||||
|
this->data(byte_to_send);
|
||||||
|
}
|
||||||
|
App.feed_wdt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// COMMAND POWER ON
|
||||||
|
ESP_LOGI(TAG, "Power on the display");
|
||||||
|
this->command(0x04);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND REFRESH SCREEN
|
||||||
|
ESP_LOGI(TAG, "Refresh the display");
|
||||||
|
this->command(0x12);
|
||||||
|
this->data(0x00);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND POWER OFF
|
||||||
|
ESP_LOGI(TAG, "Power off the display");
|
||||||
|
this->command(0x02);
|
||||||
|
this->data(0x00);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Set the display to deep sleep");
|
||||||
|
this->command(0x07);
|
||||||
|
this->data(0xA5);
|
||||||
|
}
|
||||||
|
int WaveshareEPaper7P3InF::get_width_internal() { return 800; }
|
||||||
|
int WaveshareEPaper7P3InF::get_height_internal() { return 480; }
|
||||||
|
uint32_t WaveshareEPaper7P3InF::idle_timeout_() { return 35000; }
|
||||||
|
void WaveshareEPaper7P3InF::dump_config() {
|
||||||
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Model: 7.3in-F");
|
||||||
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
|
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||||
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WaveshareEPaper7P3InF::wait_until_idle_() {
|
||||||
|
if (this->busy_pin_ == nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const uint32_t start = millis();
|
||||||
|
while (this->busy_pin_->digital_read()) {
|
||||||
|
if (millis() - start > this->idle_timeout_()) {
|
||||||
|
ESP_LOGE(TAG, "Timeout while displaying image!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
App.feed_wdt();
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
delay(200); // NOLINT
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool WaveshareEPaper7P5InV2::wait_until_idle_() {
|
bool WaveshareEPaper7P5InV2::wait_until_idle_() {
|
||||||
if (this->busy_pin_ == nullptr) {
|
if (this->busy_pin_ == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
@ -3100,6 +3734,209 @@ void WaveshareEPaper7P5InV2alt::dump_config() {
|
|||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 7.50inV2 with partial and fast refresh */
|
||||||
|
bool WaveshareEPaper7P5InV2P::wait_until_idle_() {
|
||||||
|
if (this->busy_pin_ == nullptr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t start = millis();
|
||||||
|
while (this->busy_pin_->digital_read()) {
|
||||||
|
this->command(0x71);
|
||||||
|
if (millis() - start > this->idle_timeout_()) {
|
||||||
|
ESP_LOGE(TAG, "Timeout while displaying image!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
App.feed_wdt();
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaveshareEPaper7P5InV2P::reset_() {
|
||||||
|
if (this->reset_pin_ != nullptr) {
|
||||||
|
this->reset_pin_->digital_write(true);
|
||||||
|
delay(20);
|
||||||
|
this->reset_pin_->digital_write(false);
|
||||||
|
delay(2);
|
||||||
|
this->reset_pin_->digital_write(true);
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaveshareEPaper7P5InV2P::turn_on_display_() {
|
||||||
|
this->command(0x12);
|
||||||
|
delay(100); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaveshareEPaper7P5InV2P::initialize() {
|
||||||
|
this->reset_();
|
||||||
|
|
||||||
|
// COMMAND POWER SETTING
|
||||||
|
this->command(0x01);
|
||||||
|
this->data(0x07);
|
||||||
|
this->data(0x07);
|
||||||
|
this->data(0x3f);
|
||||||
|
this->data(0x3f);
|
||||||
|
|
||||||
|
// COMMAND BOOSTER SOFT START
|
||||||
|
this->command(0x06);
|
||||||
|
this->data(0x17);
|
||||||
|
this->data(0x17);
|
||||||
|
this->data(0x28);
|
||||||
|
this->data(0x17);
|
||||||
|
|
||||||
|
// COMMAND POWER DRIVER HAT UP
|
||||||
|
this->command(0x04);
|
||||||
|
delay(100); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND PANEL SETTING
|
||||||
|
this->command(0x00);
|
||||||
|
this->data(0x1F);
|
||||||
|
|
||||||
|
// COMMAND RESOLUTION SETTING
|
||||||
|
this->command(0x61);
|
||||||
|
this->data(0x03);
|
||||||
|
this->data(0x20);
|
||||||
|
this->data(0x01);
|
||||||
|
this->data(0xE0);
|
||||||
|
|
||||||
|
// COMMAND DUAL SPI MM_EN, DUSPI_EN
|
||||||
|
this->command(0x15);
|
||||||
|
this->data(0x00);
|
||||||
|
|
||||||
|
// COMMAND VCOM AND DATA INTERVAL SETTING
|
||||||
|
this->command(0x50);
|
||||||
|
this->data(0x10);
|
||||||
|
this->data(0x07);
|
||||||
|
|
||||||
|
// COMMAND TCON SETTING
|
||||||
|
this->command(0x60);
|
||||||
|
this->data(0x22);
|
||||||
|
|
||||||
|
// COMMAND ENABLE FAST UPDATE
|
||||||
|
this->command(0xE0);
|
||||||
|
this->data(0x02);
|
||||||
|
this->command(0xE5);
|
||||||
|
this->data(0x5A);
|
||||||
|
|
||||||
|
// COMMAND POWER DRIVER HAT DOWN
|
||||||
|
this->command(0x02);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HOT WaveshareEPaper7P5InV2P::display() {
|
||||||
|
uint32_t buf_len = this->get_buffer_length_();
|
||||||
|
|
||||||
|
// COMMAND POWER ON
|
||||||
|
ESP_LOGI(TAG, "Power on the display and hat");
|
||||||
|
|
||||||
|
this->command(0x04);
|
||||||
|
delay(200); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
if (this->full_update_every_ == 1) {
|
||||||
|
this->command(0x13);
|
||||||
|
for (uint32_t i = 0; i < buf_len; i++) {
|
||||||
|
this->data(~(this->buffer_[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->turn_on_display_();
|
||||||
|
|
||||||
|
this->command(0x02);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->command(0x50);
|
||||||
|
this->data(0xA9);
|
||||||
|
this->data(0x07);
|
||||||
|
|
||||||
|
if (this->at_update_ == 0) {
|
||||||
|
// Enable fast refresh
|
||||||
|
this->command(0xE5);
|
||||||
|
this->data(0x5A);
|
||||||
|
|
||||||
|
this->command(0x92);
|
||||||
|
|
||||||
|
this->command(0x10);
|
||||||
|
delay(2);
|
||||||
|
for (uint32_t i = 0; i < buf_len; i++) {
|
||||||
|
this->data(~(this->buffer_[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(100); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
this->command(0x13);
|
||||||
|
delay(2);
|
||||||
|
for (uint32_t i = 0; i < buf_len; i++) {
|
||||||
|
this->data(this->buffer_[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(100); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
this->turn_on_display_();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Enable partial refresh
|
||||||
|
this->command(0xE5);
|
||||||
|
this->data(0x6E);
|
||||||
|
|
||||||
|
// Activate partial refresh and set window bounds
|
||||||
|
this->command(0x91);
|
||||||
|
this->command(0x90);
|
||||||
|
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x00);
|
||||||
|
this->data((get_width_internal() - 1) >> 8 & 0xFF);
|
||||||
|
this->data((get_width_internal() - 1) & 0xFF);
|
||||||
|
|
||||||
|
this->data(0x00);
|
||||||
|
this->data(0x00);
|
||||||
|
this->data((get_height_internal() - 1) >> 8 & 0xFF);
|
||||||
|
this->data((get_height_internal() - 1) & 0xFF);
|
||||||
|
|
||||||
|
this->data(0x01);
|
||||||
|
|
||||||
|
this->command(0x13);
|
||||||
|
delay(2);
|
||||||
|
for (uint32_t i = 0; i < buf_len; i++) {
|
||||||
|
this->data(this->buffer_[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(100); // NOLINT
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
this->turn_on_display_();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGV(TAG, "Before command(0x02) (>> power off)");
|
||||||
|
this->command(0x02);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
ESP_LOGV(TAG, "After command(0x02) (>> power off)");
|
||||||
|
|
||||||
|
this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WaveshareEPaper7P5InV2P::get_width_internal() { return 800; }
|
||||||
|
int WaveshareEPaper7P5InV2P::get_height_internal() { return 480; }
|
||||||
|
uint32_t WaveshareEPaper7P5InV2P::idle_timeout_() { return 10000; }
|
||||||
|
void WaveshareEPaper7P5InV2P::dump_config() {
|
||||||
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Model: 7.50inv2p");
|
||||||
|
ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
|
||||||
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
|
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||||
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
void WaveshareEPaper7P5InV2P::set_full_update_every(uint32_t full_update_every) {
|
||||||
|
this->full_update_every_ = full_update_every;
|
||||||
|
}
|
||||||
|
|
||||||
/* 7.50in-bc */
|
/* 7.50in-bc */
|
||||||
void WaveshareEPaper7P5InBC::initialize() {
|
void WaveshareEPaper7P5InBC::initialize() {
|
||||||
/* The command sequence is similar to the 7P5In display but differs in subtle ways
|
/* The command sequence is similar to the 7P5In display but differs in subtle ways
|
||||||
|
@ -27,10 +27,7 @@ class WaveshareEPaperBase : public display::DisplayBuffer,
|
|||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void setup() override {
|
void setup() override;
|
||||||
this->setup_pins_();
|
|
||||||
this->initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_safe_shutdown() override;
|
void on_safe_shutdown() override;
|
||||||
|
|
||||||
@ -86,6 +83,23 @@ class WaveshareEPaperBWR : public WaveshareEPaperBase {
|
|||||||
uint32_t get_buffer_length_() override;
|
uint32_t get_buffer_length_() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WaveshareEPaper7C : public WaveshareEPaperBase {
|
||||||
|
public:
|
||||||
|
uint8_t color_to_hex(Color color);
|
||||||
|
void fill(Color color) override;
|
||||||
|
|
||||||
|
display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void draw_absolute_pixel_internal(int x, int y, Color color) override;
|
||||||
|
uint32_t get_buffer_length_() override;
|
||||||
|
void setup() override;
|
||||||
|
void init_internal_7c_(uint32_t buffer_length);
|
||||||
|
|
||||||
|
static const int NUM_BUFFERS = 10;
|
||||||
|
uint8_t *buffers_[NUM_BUFFERS];
|
||||||
|
};
|
||||||
|
|
||||||
enum WaveshareEPaperTypeAModel {
|
enum WaveshareEPaperTypeAModel {
|
||||||
WAVESHARE_EPAPER_1_54_IN = 0,
|
WAVESHARE_EPAPER_1_54_IN = 0,
|
||||||
WAVESHARE_EPAPER_1_54_IN_V2,
|
WAVESHARE_EPAPER_1_54_IN_V2,
|
||||||
@ -160,6 +174,7 @@ enum WaveshareEPaperTypeBModel {
|
|||||||
WAVESHARE_EPAPER_2_7_IN_B_V2,
|
WAVESHARE_EPAPER_2_7_IN_B_V2,
|
||||||
WAVESHARE_EPAPER_4_2_IN,
|
WAVESHARE_EPAPER_4_2_IN,
|
||||||
WAVESHARE_EPAPER_4_2_IN_B_V2,
|
WAVESHARE_EPAPER_4_2_IN_B_V2,
|
||||||
|
WAVESHARE_EPAPER_7_3_IN_F,
|
||||||
WAVESHARE_EPAPER_7_5_IN,
|
WAVESHARE_EPAPER_7_5_IN,
|
||||||
WAVESHARE_EPAPER_7_5_INV2,
|
WAVESHARE_EPAPER_7_5_INV2,
|
||||||
WAVESHARE_EPAPER_7_5_IN_B_V2,
|
WAVESHARE_EPAPER_7_5_IN_B_V2,
|
||||||
@ -277,6 +292,25 @@ class GDEW029T5 : public WaveshareEPaper {
|
|||||||
uint8_t *old_buffer_{nullptr};
|
uint8_t *old_buffer_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GDEY029T94 : public WaveshareEPaper {
|
||||||
|
public:
|
||||||
|
void initialize() override;
|
||||||
|
|
||||||
|
void display() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void deep_sleep() override {
|
||||||
|
this->command(0x10); // Enter deep sleep
|
||||||
|
this->data(0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int get_width_internal() override;
|
||||||
|
|
||||||
|
int get_height_internal() override;
|
||||||
|
};
|
||||||
|
|
||||||
class WaveshareEPaper2P7InV2 : public WaveshareEPaper {
|
class WaveshareEPaper2P7InV2 : public WaveshareEPaper {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
@ -447,6 +481,43 @@ class WaveshareEPaper2P9InD : public WaveshareEPaper {
|
|||||||
int get_height_internal() override;
|
int get_height_internal() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GDEY042T81 : public WaveshareEPaper {
|
||||||
|
public:
|
||||||
|
GDEY042T81();
|
||||||
|
|
||||||
|
void initialize() override;
|
||||||
|
|
||||||
|
void display() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void deep_sleep() override {
|
||||||
|
// COMMAND POWER OFF
|
||||||
|
this->command(0x22);
|
||||||
|
this->data(0x83);
|
||||||
|
this->command(0x20);
|
||||||
|
// COMMAND DEEP SLEEP
|
||||||
|
this->command(0x10);
|
||||||
|
this->data(0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_full_update_every(uint32_t full_update_every);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t full_update_every_{30};
|
||||||
|
uint32_t at_update_{0};
|
||||||
|
|
||||||
|
int get_width_internal() override;
|
||||||
|
int get_height_internal() override;
|
||||||
|
uint32_t idle_timeout_() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reset_();
|
||||||
|
void update_full_();
|
||||||
|
void update_part_();
|
||||||
|
void init_display_();
|
||||||
|
};
|
||||||
|
|
||||||
class WaveshareEPaper4P2In : public WaveshareEPaper {
|
class WaveshareEPaper4P2In : public WaveshareEPaper {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
@ -518,6 +589,34 @@ class WaveshareEPaper4P2InBV2 : public WaveshareEPaper {
|
|||||||
int get_height_internal() override;
|
int get_height_internal() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WaveshareEPaper4P2InBV2BWR : public WaveshareEPaperBWR {
|
||||||
|
public:
|
||||||
|
void initialize() override;
|
||||||
|
|
||||||
|
void display() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void deep_sleep() override {
|
||||||
|
// COMMAND VCOM AND DATA INTERVAL SETTING
|
||||||
|
this->command(0x50);
|
||||||
|
this->data(0xF7); // border floating
|
||||||
|
|
||||||
|
// COMMAND POWER OFF
|
||||||
|
this->command(0x02);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// COMMAND DEEP SLEEP
|
||||||
|
this->command(0x07);
|
||||||
|
this->data(0xA5); // check code
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int get_width_internal() override;
|
||||||
|
|
||||||
|
int get_height_internal() override;
|
||||||
|
};
|
||||||
|
|
||||||
class WaveshareEPaper5P8In : public WaveshareEPaper {
|
class WaveshareEPaper5P8In : public WaveshareEPaper {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
@ -584,6 +683,39 @@ class WaveshareEPaper5P8InV2 : public WaveshareEPaper {
|
|||||||
int get_height_internal() override;
|
int get_height_internal() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WaveshareEPaper7P3InF : public WaveshareEPaper7C {
|
||||||
|
public:
|
||||||
|
void initialize() override;
|
||||||
|
|
||||||
|
void display() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int get_width_internal() override;
|
||||||
|
|
||||||
|
int get_height_internal() override;
|
||||||
|
|
||||||
|
uint32_t idle_timeout_() override;
|
||||||
|
|
||||||
|
void deep_sleep() override { ; }
|
||||||
|
|
||||||
|
bool wait_until_idle_();
|
||||||
|
|
||||||
|
bool deep_sleep_between_updates_{true};
|
||||||
|
|
||||||
|
void reset_() {
|
||||||
|
if (this->reset_pin_ != nullptr) {
|
||||||
|
this->reset_pin_->digital_write(true);
|
||||||
|
delay(20);
|
||||||
|
this->reset_pin_->digital_write(false);
|
||||||
|
delay(1);
|
||||||
|
this->reset_pin_->digital_write(true);
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
class WaveshareEPaper7P5In : public WaveshareEPaper {
|
class WaveshareEPaper7P5In : public WaveshareEPaper {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
@ -775,6 +907,43 @@ class WaveshareEPaper7P5InV2alt : public WaveshareEPaper7P5InV2 {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WaveshareEPaper7P5InV2P : public WaveshareEPaper {
|
||||||
|
public:
|
||||||
|
bool wait_until_idle_();
|
||||||
|
|
||||||
|
void initialize() override;
|
||||||
|
|
||||||
|
void display() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void deep_sleep() override {
|
||||||
|
// COMMAND POWER OFF
|
||||||
|
this->command(0x02);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
// COMMAND DEEP SLEEP
|
||||||
|
this->command(0x07);
|
||||||
|
this->data(0xA5); // check byte
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_full_update_every(uint32_t full_update_every);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int get_width_internal() override;
|
||||||
|
|
||||||
|
int get_height_internal() override;
|
||||||
|
|
||||||
|
uint32_t idle_timeout_() override;
|
||||||
|
|
||||||
|
uint32_t full_update_every_{30};
|
||||||
|
uint32_t at_update_{0};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reset_();
|
||||||
|
|
||||||
|
void turn_on_display_();
|
||||||
|
};
|
||||||
|
|
||||||
class WaveshareEPaper7P5InHDB : public WaveshareEPaper {
|
class WaveshareEPaper7P5InHDB : public WaveshareEPaper {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2025.2.0-dev"
|
__version__ = "2025.3.0-dev"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||||
|
@ -12,7 +12,7 @@ pyserial==3.5
|
|||||||
platformio==6.1.16 # When updating platformio, also update Dockerfile
|
platformio==6.1.16 # When updating platformio, also update Dockerfile
|
||||||
esptool==4.7.0
|
esptool==4.7.0
|
||||||
click==8.1.7
|
click==8.1.7
|
||||||
esphome-dashboard==20241217.1
|
esphome-dashboard==20250212.0
|
||||||
aioesphomeapi==24.6.2
|
aioesphomeapi==24.6.2
|
||||||
zeroconf==0.143.0
|
zeroconf==0.143.0
|
||||||
puremagic==1.27
|
puremagic==1.27
|
||||||
|
@ -121,6 +121,14 @@ number:
|
|||||||
max_value: 100
|
max_value: 100
|
||||||
step: 1
|
step: 1
|
||||||
|
|
||||||
|
valve:
|
||||||
|
- platform: template
|
||||||
|
name: "Template Valve"
|
||||||
|
lambda: |-
|
||||||
|
return VALVE_OPEN;
|
||||||
|
optimistic: true
|
||||||
|
has_position: true
|
||||||
|
|
||||||
prometheus:
|
prometheus:
|
||||||
include_internal: true
|
include_internal: true
|
||||||
relabel:
|
relabel:
|
||||||
|
@ -463,6 +463,26 @@ display:
|
|||||||
lambda: |-
|
lambda: |-
|
||||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
|
- platform: waveshare_epaper
|
||||||
|
id: epd_gdew042t81
|
||||||
|
model: gdey042t81
|
||||||
|
spi_id: spi_waveshare_epaper
|
||||||
|
cs_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${cs_pin}
|
||||||
|
dc_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${dc_pin}
|
||||||
|
busy_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${busy_pin}
|
||||||
|
reset_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${reset_pin}
|
||||||
|
full_update_every: 30
|
||||||
|
lambda: |-
|
||||||
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
# 4.2 inch displays
|
# 4.2 inch displays
|
||||||
- platform: waveshare_epaper
|
- platform: waveshare_epaper
|
||||||
id: epd_4_20
|
id: epd_4_20
|
||||||
@ -502,6 +522,25 @@ display:
|
|||||||
lambda: |-
|
lambda: |-
|
||||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
|
- platform: waveshare_epaper
|
||||||
|
id: epd_4_20in_bv2_bwr
|
||||||
|
model: 4.20in-bv2-bwr
|
||||||
|
spi_id: spi_waveshare_epaper
|
||||||
|
cs_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${cs_pin}
|
||||||
|
dc_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${dc_pin}
|
||||||
|
busy_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${busy_pin}
|
||||||
|
reset_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${reset_pin}
|
||||||
|
lambda: |-
|
||||||
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
# 5.83 inch displays
|
# 5.83 inch displays
|
||||||
- platform: waveshare_epaper
|
- platform: waveshare_epaper
|
||||||
id: epd_5_83
|
id: epd_5_83
|
||||||
@ -675,6 +714,26 @@ display:
|
|||||||
lambda: |-
|
lambda: |-
|
||||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
|
- platform: waveshare_epaper
|
||||||
|
id: epd_7_50inv2p
|
||||||
|
model: 7.50inv2p
|
||||||
|
spi_id: spi_waveshare_epaper
|
||||||
|
cs_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${cs_pin}
|
||||||
|
dc_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${dc_pin}
|
||||||
|
busy_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${busy_pin}
|
||||||
|
reset_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: ${reset_pin}
|
||||||
|
full_update_every: 30
|
||||||
|
lambda: |-
|
||||||
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
- platform: waveshare_epaper
|
- platform: waveshare_epaper
|
||||||
id: epd_7_50hdb
|
id: epd_7_50hdb
|
||||||
model: 7.50in-hd-b
|
model: 7.50in-hd-b
|
||||||
|
Loading…
x
Reference in New Issue
Block a user