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
08360487b5
@ -18,8 +18,8 @@ namespace esphome {
|
|||||||
namespace http_request {
|
namespace http_request {
|
||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
const char *name;
|
std::string name;
|
||||||
const char *value;
|
std::string value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some common HTTP status codes
|
// Some common HTTP status codes
|
||||||
|
@ -96,7 +96,7 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::start(std::string url, std::s
|
|||||||
container->client_.setUserAgent(this->useragent_);
|
container->client_.setUserAgent(this->useragent_);
|
||||||
}
|
}
|
||||||
for (const auto &header : headers) {
|
for (const auto &header : headers) {
|
||||||
container->client_.addHeader(header.name, header.value, false, true);
|
container->client_.addHeader(header.name.c_str(), header.value.c_str(), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returned needed headers must be collected before the requests
|
// returned needed headers must be collected before the requests
|
||||||
|
@ -84,7 +84,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
|
|||||||
container->set_secure(secure);
|
container->set_secure(secure);
|
||||||
|
|
||||||
for (const auto &header : headers) {
|
for (const auto &header : headers) {
|
||||||
esp_http_client_set_header(client, header.name, header.value);
|
esp_http_client_set_header(client, header.name.c_str(), header.value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
const int body_len = body.length();
|
const int body_len = body.length();
|
||||||
|
@ -25,6 +25,15 @@ void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DownloadBuffer::DownloadBuffer(size_t size) : size_(size) {
|
||||||
|
this->buffer_ = this->allocator_.allocate(size);
|
||||||
|
this->reset();
|
||||||
|
if (!this->buffer_) {
|
||||||
|
ESP_LOGE(TAG, "Initial allocation of download buffer failed!");
|
||||||
|
this->size_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *DownloadBuffer::data(size_t offset) {
|
uint8_t *DownloadBuffer::data(size_t offset) {
|
||||||
if (offset > this->size_) {
|
if (offset > this->size_) {
|
||||||
ESP_LOGE(TAG, "Tried to access beyond download buffer bounds!!!");
|
ESP_LOGE(TAG, "Tried to access beyond download buffer bounds!!!");
|
||||||
@ -46,12 +55,13 @@ size_t DownloadBuffer::resize(size_t size) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
this->allocator_.deallocate(this->buffer_, this->size_);
|
this->allocator_.deallocate(this->buffer_, this->size_);
|
||||||
this->size_ = size;
|
|
||||||
this->buffer_ = this->allocator_.allocate(size);
|
this->buffer_ = this->allocator_.allocate(size);
|
||||||
this->reset();
|
this->reset();
|
||||||
if (this->buffer_) {
|
if (this->buffer_) {
|
||||||
|
this->size_ = size;
|
||||||
return size;
|
return size;
|
||||||
} else {
|
} else {
|
||||||
|
this->size_ = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,12 @@ class ImageDecoder {
|
|||||||
* @brief Initialize the decoder.
|
* @brief Initialize the decoder.
|
||||||
*
|
*
|
||||||
* @param download_size The total number of bytes that need to be downloaded for the image.
|
* @param download_size The total number of bytes that need to be downloaded for the image.
|
||||||
|
* @return int Returns 0 on success, a {@see DecodeError} value in case of an error.
|
||||||
*/
|
*/
|
||||||
virtual void prepare(size_t download_size) { this->download_size_ = download_size; }
|
virtual int prepare(size_t download_size) {
|
||||||
|
this->download_size_ = download_size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Decode a part of the image. It will try reading from the buffer.
|
* @brief Decode a part of the image. It will try reading from the buffer.
|
||||||
@ -83,10 +87,7 @@ class ImageDecoder {
|
|||||||
|
|
||||||
class DownloadBuffer {
|
class DownloadBuffer {
|
||||||
public:
|
public:
|
||||||
DownloadBuffer(size_t size) : size_(size) {
|
DownloadBuffer(size_t size);
|
||||||
this->buffer_ = this->allocator_.allocate(size);
|
|
||||||
this->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); }
|
virtual ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); }
|
||||||
|
|
||||||
|
@ -41,13 +41,14 @@ static int draw_callback(JPEGDRAW *jpeg) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JpegDecoder::prepare(size_t download_size) {
|
int JpegDecoder::prepare(size_t download_size) {
|
||||||
ImageDecoder::prepare(download_size);
|
ImageDecoder::prepare(download_size);
|
||||||
auto size = this->image_->resize_download_buffer(download_size);
|
auto size = this->image_->resize_download_buffer(download_size);
|
||||||
if (size < download_size) {
|
if (size < download_size) {
|
||||||
ESP_LOGE(TAG, "Resize failed!");
|
ESP_LOGE(TAG, "Download buffer resize failed!");
|
||||||
// TODO: return an error code;
|
return DECODE_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
|
int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
|
||||||
|
@ -21,7 +21,7 @@ class JpegDecoder : public ImageDecoder {
|
|||||||
JpegDecoder(OnlineImage *image) : ImageDecoder(image) {}
|
JpegDecoder(OnlineImage *image) : ImageDecoder(image) {}
|
||||||
~JpegDecoder() override {}
|
~JpegDecoder() override {}
|
||||||
|
|
||||||
void prepare(size_t download_size) override;
|
int prepare(size_t download_size) override;
|
||||||
int HOT decode(uint8_t *buffer, size_t size) override;
|
int HOT decode(uint8_t *buffer, size_t size) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -124,7 +124,7 @@ void OnlineImage::update() {
|
|||||||
default:
|
default:
|
||||||
accept_mime_type = "image/*";
|
accept_mime_type = "image/*";
|
||||||
}
|
}
|
||||||
accept_header.value = (accept_mime_type + ",*/*;q=0.8").c_str();
|
accept_header.value = accept_mime_type + ",*/*;q=0.8";
|
||||||
|
|
||||||
headers.push_back(accept_header);
|
headers.push_back(accept_header);
|
||||||
|
|
||||||
@ -178,7 +178,12 @@ void OnlineImage::update() {
|
|||||||
this->download_error_callback_.call();
|
this->download_error_callback_.call();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->decoder_->prepare(total_size);
|
auto prepare_result = this->decoder_->prepare(total_size);
|
||||||
|
if (prepare_result < 0) {
|
||||||
|
this->end_connection_();
|
||||||
|
this->download_error_callback_.call();
|
||||||
|
return;
|
||||||
|
}
|
||||||
ESP_LOGI(TAG, "Downloading image (Size: %d)", total_size);
|
ESP_LOGI(TAG, "Downloading image (Size: %d)", total_size);
|
||||||
this->start_time_ = ::time(nullptr);
|
this->start_time_ = ::time(nullptr);
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,16 @@ static void draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, ui
|
|||||||
decoder->draw(x, y, w, h, color);
|
decoder->draw(x, y, w, h, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PngDecoder::prepare(size_t download_size) {
|
int PngDecoder::prepare(size_t download_size) {
|
||||||
ImageDecoder::prepare(download_size);
|
ImageDecoder::prepare(download_size);
|
||||||
|
if (!this->pngle_) {
|
||||||
|
ESP_LOGE(TAG, "PNG decoder engine not initialized!");
|
||||||
|
return DECODE_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
pngle_set_user_data(this->pngle_, this);
|
pngle_set_user_data(this->pngle_, this);
|
||||||
pngle_set_init_callback(this->pngle_, init_callback);
|
pngle_set_init_callback(this->pngle_, init_callback);
|
||||||
pngle_set_draw_callback(this->pngle_, draw_callback);
|
pngle_set_draw_callback(this->pngle_, draw_callback);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HOT PngDecoder::decode(uint8_t *buffer, size_t size) {
|
int HOT PngDecoder::decode(uint8_t *buffer, size_t size) {
|
||||||
|
@ -21,7 +21,7 @@ class PngDecoder : public ImageDecoder {
|
|||||||
PngDecoder(OnlineImage *image) : ImageDecoder(image), pngle_(pngle_new()) {}
|
PngDecoder(OnlineImage *image) : ImageDecoder(image), pngle_(pngle_new()) {}
|
||||||
~PngDecoder() override { pngle_destroy(this->pngle_); }
|
~PngDecoder() override { pngle_destroy(this->pngle_); }
|
||||||
|
|
||||||
void prepare(size_t download_size) override;
|
int prepare(size_t download_size) override;
|
||||||
int HOT decode(uint8_t *buffer, size_t size) override;
|
int HOT decode(uint8_t *buffer, size_t size) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -182,13 +182,21 @@ AudioPipelineState AudioPipeline::process_state() {
|
|||||||
if (event_bits & EventGroupBits::PIPELINE_COMMAND_STOP) {
|
if (event_bits & EventGroupBits::PIPELINE_COMMAND_STOP) {
|
||||||
// Stop command is fully processed, so clear the command bit
|
// Stop command is fully processed, so clear the command bit
|
||||||
xEventGroupClearBits(this->event_group_, EventGroupBits::PIPELINE_COMMAND_STOP);
|
xEventGroupClearBits(this->event_group_, EventGroupBits::PIPELINE_COMMAND_STOP);
|
||||||
|
this->hard_stop_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->is_playing_) {
|
if (!this->is_playing_) {
|
||||||
// The tasks have been stopped for two ``process_state`` calls in a row, so delete the tasks
|
// The tasks have been stopped for two ``process_state`` calls in a row, so delete the tasks
|
||||||
if ((this->read_task_handle_ != nullptr) || (this->decode_task_handle_ != nullptr)) {
|
if ((this->read_task_handle_ != nullptr) || (this->decode_task_handle_ != nullptr)) {
|
||||||
this->delete_tasks_();
|
this->delete_tasks_();
|
||||||
this->speaker_->stop();
|
if (this->hard_stop_) {
|
||||||
|
// Stop command was sent, so immediately end of the playback
|
||||||
|
this->speaker_->stop();
|
||||||
|
this->hard_stop_ = false;
|
||||||
|
} else {
|
||||||
|
// Decoded all the audio, so let the speaker finish playing before stopping
|
||||||
|
this->speaker_->finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->is_playing_ = false;
|
this->is_playing_ = false;
|
||||||
|
@ -112,6 +112,7 @@ class AudioPipeline {
|
|||||||
|
|
||||||
uint32_t playback_ms_{0};
|
uint32_t playback_ms_{0};
|
||||||
|
|
||||||
|
bool hard_stop_{false};
|
||||||
bool is_playing_{false};
|
bool is_playing_{false};
|
||||||
bool pause_state_{false};
|
bool pause_state_{false};
|
||||||
bool task_stack_in_psram_;
|
bool task_stack_in_psram_;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "voice_assistant.h"
|
#include "voice_assistant.h"
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
|
||||||
#ifdef USE_VOICE_ASSISTANT
|
#ifdef USE_VOICE_ASSISTANT
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ void VoiceAssistant::clear_buffers_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SPEAKER
|
#ifdef USE_SPEAKER
|
||||||
if (this->speaker_buffer_ != nullptr) {
|
if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) {
|
||||||
memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE);
|
memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE);
|
||||||
|
|
||||||
this->speaker_buffer_size_ = 0;
|
this->speaker_buffer_size_ = 0;
|
||||||
@ -159,7 +160,7 @@ void VoiceAssistant::deallocate_buffers_() {
|
|||||||
this->input_buffer_ = nullptr;
|
this->input_buffer_ = nullptr;
|
||||||
|
|
||||||
#ifdef USE_SPEAKER
|
#ifdef USE_SPEAKER
|
||||||
if (this->speaker_buffer_ != nullptr) {
|
if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) {
|
||||||
ExternalRAMAllocator<uint8_t> speaker_deallocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
ExternalRAMAllocator<uint8_t> speaker_deallocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||||
speaker_deallocator.deallocate(this->speaker_buffer_, SPEAKER_BUFFER_SIZE);
|
speaker_deallocator.deallocate(this->speaker_buffer_, SPEAKER_BUFFER_SIZE);
|
||||||
this->speaker_buffer_ = nullptr;
|
this->speaker_buffer_ = nullptr;
|
||||||
@ -389,14 +390,7 @@ void VoiceAssistant::loop() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (playing) {
|
if (playing) {
|
||||||
this->set_timeout("playing", 2000, [this]() {
|
this->start_playback_timeout_();
|
||||||
this->cancel_timeout("speaker-timeout");
|
|
||||||
this->set_state_(State::IDLE, State::IDLE);
|
|
||||||
|
|
||||||
api::VoiceAssistantAnnounceFinished msg;
|
|
||||||
msg.success = true;
|
|
||||||
this->api_client_->send_voice_assistant_announce_finished(msg);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -614,6 +608,8 @@ void VoiceAssistant::request_stop() {
|
|||||||
this->desired_state_ = State::IDLE;
|
this->desired_state_ = State::IDLE;
|
||||||
break;
|
break;
|
||||||
case State::AWAITING_RESPONSE:
|
case State::AWAITING_RESPONSE:
|
||||||
|
this->signal_stop_();
|
||||||
|
break;
|
||||||
case State::STREAMING_RESPONSE:
|
case State::STREAMING_RESPONSE:
|
||||||
case State::RESPONSE_FINISHED:
|
case State::RESPONSE_FINISHED:
|
||||||
break; // Let the incoming audio stream finish then it will go to idle.
|
break; // Let the incoming audio stream finish then it will go to idle.
|
||||||
@ -631,6 +627,17 @@ void VoiceAssistant::signal_stop_() {
|
|||||||
this->api_client_->send_voice_assistant_request(msg);
|
this->api_client_->send_voice_assistant_request(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoiceAssistant::start_playback_timeout_() {
|
||||||
|
this->set_timeout("playing", 100, [this]() {
|
||||||
|
this->cancel_timeout("speaker-timeout");
|
||||||
|
this->set_state_(State::IDLE, State::IDLE);
|
||||||
|
|
||||||
|
api::VoiceAssistantAnnounceFinished msg;
|
||||||
|
msg.success = true;
|
||||||
|
this->api_client_->send_voice_assistant_announce_finished(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
||||||
ESP_LOGD(TAG, "Event Type: %" PRId32, msg.event_type);
|
ESP_LOGD(TAG, "Event Type: %" PRId32, msg.event_type);
|
||||||
switch (msg.event_type) {
|
switch (msg.event_type) {
|
||||||
@ -715,6 +722,8 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|||||||
#ifdef USE_MEDIA_PLAYER
|
#ifdef USE_MEDIA_PLAYER
|
||||||
if (this->media_player_ != nullptr) {
|
if (this->media_player_ != nullptr) {
|
||||||
this->media_player_->make_call().set_media_url(url).set_announcement(true).perform();
|
this->media_player_->make_call().set_media_url(url).set_announcement(true).perform();
|
||||||
|
// Start the playback timeout, as the media player state isn't immediately updated
|
||||||
|
this->start_playback_timeout_();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
this->tts_end_trigger_->trigger(url);
|
this->tts_end_trigger_->trigger(url);
|
||||||
@ -725,7 +734,11 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|||||||
}
|
}
|
||||||
case api::enums::VOICE_ASSISTANT_RUN_END: {
|
case api::enums::VOICE_ASSISTANT_RUN_END: {
|
||||||
ESP_LOGD(TAG, "Assist Pipeline ended");
|
ESP_LOGD(TAG, "Assist Pipeline ended");
|
||||||
if (this->state_ == State::STREAMING_MICROPHONE) {
|
if ((this->state_ == State::STARTING_PIPELINE) || (this->state_ == State::AWAITING_RESPONSE)) {
|
||||||
|
// Pipeline ended before starting microphone
|
||||||
|
// Or there wasn't a TTS start event ("nevermind")
|
||||||
|
this->set_state_(State::IDLE, State::IDLE);
|
||||||
|
} else if (this->state_ == State::STREAMING_MICROPHONE) {
|
||||||
this->ring_buffer_->reset();
|
this->ring_buffer_->reset();
|
||||||
#ifdef USE_ESP_ADF
|
#ifdef USE_ESP_ADF
|
||||||
if (this->use_wake_word_) {
|
if (this->use_wake_word_) {
|
||||||
@ -736,9 +749,6 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|||||||
{
|
{
|
||||||
this->set_state_(State::IDLE, State::IDLE);
|
this->set_state_(State::IDLE, State::IDLE);
|
||||||
}
|
}
|
||||||
} else if (this->state_ == State::AWAITING_RESPONSE) {
|
|
||||||
// No TTS start event ("nevermind")
|
|
||||||
this->set_state_(State::IDLE, State::IDLE);
|
|
||||||
}
|
}
|
||||||
this->defer([this]() { this->end_trigger_->trigger(); });
|
this->defer([this]() { this->end_trigger_->trigger(); });
|
||||||
break;
|
break;
|
||||||
|
@ -40,6 +40,7 @@ enum VoiceAssistantFeature : uint32_t {
|
|||||||
FEATURE_SPEAKER = 1 << 1,
|
FEATURE_SPEAKER = 1 << 1,
|
||||||
FEATURE_API_AUDIO = 1 << 2,
|
FEATURE_API_AUDIO = 1 << 2,
|
||||||
FEATURE_TIMERS = 1 << 3,
|
FEATURE_TIMERS = 1 << 3,
|
||||||
|
FEATURE_ANNOUNCE = 1 << 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class State {
|
enum class State {
|
||||||
@ -136,6 +137,12 @@ class VoiceAssistant : public Component {
|
|||||||
flags |= VoiceAssistantFeature::FEATURE_TIMERS;
|
flags |= VoiceAssistantFeature::FEATURE_TIMERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_MEDIA_PLAYER
|
||||||
|
if (this->media_player_ != nullptr) {
|
||||||
|
flags |= VoiceAssistantFeature::FEATURE_ANNOUNCE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,6 +216,7 @@ class VoiceAssistant : public Component {
|
|||||||
void set_state_(State state);
|
void set_state_(State state);
|
||||||
void set_state_(State state, State desired_state);
|
void set_state_(State state, State desired_state);
|
||||||
void signal_stop_();
|
void signal_stop_();
|
||||||
|
void start_playback_timeout_();
|
||||||
|
|
||||||
std::unique_ptr<socket::Socket> socket_ = nullptr;
|
std::unique_ptr<socket::Socket> socket_ = nullptr;
|
||||||
struct sockaddr_storage dest_addr_;
|
struct sockaddr_storage dest_addr_;
|
||||||
|
@ -55,6 +55,9 @@ GDEW029T5 = waveshare_epaper_ns.class_("GDEW029T5", WaveshareEPaper)
|
|||||||
WaveshareEPaper2P9InDKE = waveshare_epaper_ns.class_(
|
WaveshareEPaper2P9InDKE = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper2P9InDKE", WaveshareEPaper
|
"WaveshareEPaper2P9InDKE", WaveshareEPaper
|
||||||
)
|
)
|
||||||
|
WaveshareEPaper2P9InD = waveshare_epaper_ns.class_(
|
||||||
|
"WaveshareEPaper2P9InD", WaveshareEPaper
|
||||||
|
)
|
||||||
WaveshareEPaper4P2In = waveshare_epaper_ns.class_(
|
WaveshareEPaper4P2In = waveshare_epaper_ns.class_(
|
||||||
"WaveshareEPaper4P2In", WaveshareEPaper
|
"WaveshareEPaper4P2In", WaveshareEPaper
|
||||||
)
|
)
|
||||||
@ -120,7 +123,7 @@ MODELS = {
|
|||||||
"2.13in-ttgo-b74": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B74),
|
"2.13in-ttgo-b74": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B74),
|
||||||
"2.90in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN),
|
"2.90in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN),
|
||||||
"2.90inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN_V2),
|
"2.90inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN_V2),
|
||||||
"gdew029t5": ("b", GDEW029T5),
|
"gdew029t5": ("c", GDEW029T5),
|
||||||
"2.70in": ("b", WaveshareEPaper2P7In),
|
"2.70in": ("b", WaveshareEPaper2P7In),
|
||||||
"2.70in-b": ("b", WaveshareEPaper2P7InB),
|
"2.70in-b": ("b", WaveshareEPaper2P7InB),
|
||||||
"2.70in-bv2": ("b", WaveshareEPaper2P7InBV2),
|
"2.70in-bv2": ("b", WaveshareEPaper2P7InBV2),
|
||||||
@ -128,6 +131,7 @@ MODELS = {
|
|||||||
"2.90in-b": ("b", WaveshareEPaper2P9InB),
|
"2.90in-b": ("b", WaveshareEPaper2P9InB),
|
||||||
"2.90in-bv3": ("b", WaveshareEPaper2P9InBV3),
|
"2.90in-bv3": ("b", WaveshareEPaper2P9InBV3),
|
||||||
"2.90inv2-r2": ("c", WaveshareEPaper2P9InV2R2),
|
"2.90inv2-r2": ("c", WaveshareEPaper2P9InV2R2),
|
||||||
|
"2.90in-d": ("b", WaveshareEPaper2P9InD),
|
||||||
"2.90in-dke": ("c", WaveshareEPaper2P9InDKE),
|
"2.90in-dke": ("c", WaveshareEPaper2P9InDKE),
|
||||||
"4.20in": ("b", WaveshareEPaper4P2In),
|
"4.20in": ("b", WaveshareEPaper4P2In),
|
||||||
"4.20in-bv2": ("b", WaveshareEPaper4P2InBV2),
|
"4.20in-bv2": ("b", WaveshareEPaper4P2InBV2),
|
||||||
|
@ -1211,6 +1211,93 @@ void WaveshareEPaper2P9InB::dump_config() {
|
|||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================================================
|
||||||
|
// Waveshare 2.9-inch E-Paper (Type D)
|
||||||
|
// Waveshare WIKI: https://www.waveshare.com/wiki/Pico-ePaper-2.9-D
|
||||||
|
// Datasheet: https://www.waveshare.com/w/upload/b/b5/2.9inch_e-Paper_(D)_Specification.pdf
|
||||||
|
// ========================================================
|
||||||
|
|
||||||
|
void WaveshareEPaper2P9InD::initialize() {
|
||||||
|
// EPD hardware init start
|
||||||
|
this->reset_();
|
||||||
|
|
||||||
|
// Booster Soft Start
|
||||||
|
this->command(0x06); // Command: BTST
|
||||||
|
this->data(0x17); // Soft start configuration Phase A
|
||||||
|
this->data(0x17); // Soft start configuration Phase B
|
||||||
|
this->data(0x17); // Soft start configuration Phase C
|
||||||
|
|
||||||
|
// Power Setting
|
||||||
|
this->command(0x01); // Command: PWR
|
||||||
|
this->data(0x03); // Intern DC/DC for VDH/VDL and VGH/VGL
|
||||||
|
this->data(0x00); // Default configuration VCOM_HV and VGHL_LV
|
||||||
|
this->data(0x2b); // VDH = 10.8 V
|
||||||
|
this->data(0x2b); // VDL = -10.8 V
|
||||||
|
|
||||||
|
// Power ON
|
||||||
|
this->command(0x04); // Command: PON
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// Panel settings
|
||||||
|
this->command(0x00); // Command: PSR
|
||||||
|
this->data(0x1F); // LUT from OTP, black and white mode, default scan
|
||||||
|
|
||||||
|
// PLL Control
|
||||||
|
this->command(0x30); // Command: PLL
|
||||||
|
this->data(0x3A); // Default PLL frequency
|
||||||
|
|
||||||
|
// Resolution settings
|
||||||
|
this->command(0x61); // Command: TRES
|
||||||
|
this->data(0x80); // Width: 128
|
||||||
|
this->data(0x01); // Height MSB: 296
|
||||||
|
this->data(0x28); // Height LSB: 296
|
||||||
|
|
||||||
|
// VCOM and data interval settings
|
||||||
|
this->command(0x50); // Command: CDI
|
||||||
|
this->data(0x77);
|
||||||
|
|
||||||
|
// VCOM_DC settings
|
||||||
|
this->command(0x82); // Command: VDCS
|
||||||
|
this->data(0x12); // Dafault VCOM_DC
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaveshareEPaper2P9InD::display() {
|
||||||
|
// Start transmitting old data (clearing buffer)
|
||||||
|
this->command(0x10); // Command: DTM1 (OLD frame data)
|
||||||
|
this->start_data_();
|
||||||
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
||||||
|
this->end_data_();
|
||||||
|
|
||||||
|
// Start transmitting new data (updated content)
|
||||||
|
this->command(0x13); // Command: DTM2 (NEW frame data)
|
||||||
|
this->start_data_();
|
||||||
|
this->write_array(this->buffer_, this->get_buffer_length_());
|
||||||
|
this->end_data_();
|
||||||
|
|
||||||
|
// Refresh Display
|
||||||
|
this->command(0x12); // Command: DRF
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// Enter Power Off
|
||||||
|
this->command(0x02); // Command: POF
|
||||||
|
this->wait_until_idle_();
|
||||||
|
|
||||||
|
// Enter Deep Sleep
|
||||||
|
this->command(0x07); // Command: DSLP
|
||||||
|
this->data(0xA5);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WaveshareEPaper2P9InD::get_width_internal() { return 128; }
|
||||||
|
int WaveshareEPaper2P9InD::get_height_internal() { return 296; }
|
||||||
|
void WaveshareEPaper2P9InD::dump_config() {
|
||||||
|
LOG_DISPLAY("", "Waveshare E-Paper", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Model: 2.9in (D)");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
// DKE 2.9
|
// DKE 2.9
|
||||||
// https://www.badge.team/docs/badges/sha2017/hardware/#e-ink-display-the-dke-group-depg0290b1
|
// https://www.badge.team/docs/badges/sha2017/hardware/#e-ink-display-the-dke-group-depg0290b1
|
||||||
// https://www.badge.team/docs/badges/sha2017/hardware/DEPG0290B01V3.0.pdf
|
// https://www.badge.team/docs/badges/sha2017/hardware/DEPG0290B01V3.0.pdf
|
||||||
@ -1596,15 +1683,108 @@ void WaveshareEPaper2P9InV2R2::set_full_update_every(uint32_t full_update_every)
|
|||||||
// 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
|
||||||
|
// - https://github.com/ZinggJM/GxEPD2/blob/master/src/epd/GxEPD2_290_T5.cpp
|
||||||
|
// - http://www.e-paper-display.com/GDEW029T5%20V3.1%20Specification5c22.pdf?
|
||||||
// ========================================================
|
// ========================================================
|
||||||
|
|
||||||
void GDEW029T5::initialize() {
|
// full screen update LUT
|
||||||
// from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
|
static const uint8_t LUT_20_VCOMDC_29_5[] = {
|
||||||
// EPD hardware init start
|
0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x60, 0x28, 0x28, 0x00, 0x00, 0x01, 0x00, 0x14, 0x00,
|
||||||
this->reset_();
|
0x00, 0x00, 0x01, 0x00, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_21_WW_29_5[] = {
|
||||||
|
0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_22_BW_29_5[] = {
|
||||||
|
0x40, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x40, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_23_WB_29_5[] = {
|
||||||
|
0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_24_BB_29_5[] = {
|
||||||
|
0x80, 0x08, 0x00, 0x00, 0x00, 0x02, 0x90, 0x28, 0x28, 0x00, 0x00, 0x01, 0x80, 0x14,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0x50, 0x12, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
// partial screen update LUT
|
||||||
|
static const uint8_t LUT_20_VCOMDC_PARTIAL_29_5[] = {
|
||||||
|
0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_21_WW_PARTIAL_29_5[] = {
|
||||||
|
0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_22_BW_PARTIAL_29_5[] = {
|
||||||
|
0x80, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_23_WB_PARTIAL_29_5[] = {
|
||||||
|
0x40, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t LUT_24_BB_PARTIAL_29_5[] = {
|
||||||
|
0x00, 0x20, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
void GDEW029T5::power_on_() {
|
||||||
|
if (!this->power_is_on_) {
|
||||||
|
this->command(0x04);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
}
|
||||||
|
this->power_is_on_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDEW029T5::power_off_() {
|
||||||
|
this->command(0x02);
|
||||||
|
this->wait_until_idle_();
|
||||||
|
this->power_is_on_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDEW029T5::deep_sleep() {
|
||||||
|
this->power_off_();
|
||||||
|
if (this->deep_sleep_between_updates_) {
|
||||||
|
this->command(0x07); // deep sleep
|
||||||
|
this->data(0xA5); // check code
|
||||||
|
ESP_LOGD(TAG, "go to deep sleep");
|
||||||
|
this->is_deep_sleep_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDEW029T5::init_display_() {
|
||||||
|
// from https://github.com/ZinggJM/GxEPD2/blob/master/src/epd/GxEPD2_290_T5.cpp
|
||||||
|
|
||||||
|
// Hardware Initialization
|
||||||
|
if (this->deep_sleep_between_updates_ && this->is_deep_sleep_) {
|
||||||
|
ESP_LOGI(TAG, "wake up from deep sleep");
|
||||||
|
this->reset_();
|
||||||
|
this->is_deep_sleep_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
// COMMAND POWER SETTINGS
|
// COMMAND POWER SETTINGS
|
||||||
this->command(0x00);
|
this->command(0x01);
|
||||||
this->data(0x03);
|
this->data(0x03);
|
||||||
this->data(0x00);
|
this->data(0x00);
|
||||||
this->data(0x2b);
|
this->data(0x2b);
|
||||||
@ -1617,40 +1797,122 @@ void GDEW029T5::initialize() {
|
|||||||
this->data(0x17);
|
this->data(0x17);
|
||||||
this->data(0x17);
|
this->data(0x17);
|
||||||
|
|
||||||
// COMMAND POWER ON
|
this->power_on_();
|
||||||
this->command(0x04);
|
|
||||||
this->wait_until_idle_();
|
|
||||||
|
|
||||||
// Not sure what this does but it's in the Adafruit EPD library
|
|
||||||
this->command(0xFF);
|
|
||||||
this->wait_until_idle_();
|
|
||||||
|
|
||||||
// COMMAND PANEL SETTING
|
// COMMAND PANEL SETTING
|
||||||
this->command(0x00);
|
this->command(0x00);
|
||||||
// 128x296 resolution: 10
|
// 128x296 resolution: 10
|
||||||
// LUT from OTP: 0
|
// LUT from register: 1
|
||||||
// B/W mode (doesn't work): 1
|
// B/W mode (doesn't work): 1
|
||||||
// scan-up: 1
|
// scan-up: 1
|
||||||
// shift-right: 1
|
// shift-right: 1
|
||||||
// booster ON: 1
|
// booster ON: 1
|
||||||
// no soft reset: 1
|
// no soft reset: 1
|
||||||
this->data(0b10011111);
|
this->data(0b10111111);
|
||||||
|
this->data(0x0d); // VCOM to 0V fast
|
||||||
|
this->command(0x30); // PLL setting
|
||||||
|
this->data(0x3a); // 3a 100HZ 29 150Hz 39 200HZ 31 171HZ
|
||||||
|
this->command(0x61); // resolution setting
|
||||||
|
this->data(this->get_width_internal());
|
||||||
|
this->data(this->get_height_internal() >> 8);
|
||||||
|
this->data(this->get_height_internal() & 0xFF);
|
||||||
|
|
||||||
// COMMAND RESOLUTION SETTING
|
ESP_LOGD(TAG, "panel setting done");
|
||||||
// set to 128x296 by COMMAND PANEL SETTING
|
|
||||||
|
|
||||||
// COMMAND VCOM AND DATA INTERVAL SETTING
|
|
||||||
// use defaults for white border and ESPHome image polarity
|
|
||||||
|
|
||||||
// EPD hardware init end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDEW029T5::initialize() {
|
||||||
|
// from https://www.waveshare.com/w/upload/b/bb/2.9inch-e-paper-b-specification.pdf, page 37
|
||||||
|
if (this->reset_pin_ != nullptr)
|
||||||
|
this->deep_sleep_between_updates_ = true;
|
||||||
|
|
||||||
|
// old buffer for partial update
|
||||||
|
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||||
|
this->old_buffer_ = allocator.allocate(this->get_buffer_length_());
|
||||||
|
if (this->old_buffer_ == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "Could not allocate old buffer for display!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < this->get_buffer_length_(); i++) {
|
||||||
|
this->old_buffer_[i] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize for full(normal) update
|
||||||
|
void GDEW029T5::init_full_() {
|
||||||
|
this->init_display_();
|
||||||
|
this->command(0x82); // vcom_DC setting
|
||||||
|
this->data(0x08);
|
||||||
|
this->command(0X50); // VCOM AND DATA INTERVAL SETTING
|
||||||
|
this->data(0x97); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
|
||||||
|
this->command(0x20);
|
||||||
|
this->write_lut_(LUT_20_VCOMDC_29_5, sizeof(LUT_20_VCOMDC_29_5));
|
||||||
|
this->command(0x21);
|
||||||
|
this->write_lut_(LUT_21_WW_29_5, sizeof(LUT_21_WW_29_5));
|
||||||
|
this->command(0x22);
|
||||||
|
this->write_lut_(LUT_22_BW_29_5, sizeof(LUT_22_BW_29_5));
|
||||||
|
this->command(0x23);
|
||||||
|
this->write_lut_(LUT_23_WB_29_5, sizeof(LUT_23_WB_29_5));
|
||||||
|
this->command(0x24);
|
||||||
|
this->write_lut_(LUT_24_BB_29_5, sizeof(LUT_24_BB_29_5));
|
||||||
|
ESP_LOGD(TAG, "initialized full update");
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialzie for partial update
|
||||||
|
void GDEW029T5::init_partial_() {
|
||||||
|
this->init_display_();
|
||||||
|
this->command(0x82); // vcom_DC setting
|
||||||
|
this->data(0x08);
|
||||||
|
this->command(0X50); // VCOM AND DATA INTERVAL SETTING
|
||||||
|
this->data(0x17); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
|
||||||
|
this->command(0x20);
|
||||||
|
this->write_lut_(LUT_20_VCOMDC_PARTIAL_29_5, sizeof(LUT_20_VCOMDC_PARTIAL_29_5));
|
||||||
|
this->command(0x21);
|
||||||
|
this->write_lut_(LUT_21_WW_PARTIAL_29_5, sizeof(LUT_21_WW_PARTIAL_29_5));
|
||||||
|
this->command(0x22);
|
||||||
|
this->write_lut_(LUT_22_BW_PARTIAL_29_5, sizeof(LUT_22_BW_PARTIAL_29_5));
|
||||||
|
this->command(0x23);
|
||||||
|
this->write_lut_(LUT_23_WB_PARTIAL_29_5, sizeof(LUT_23_WB_PARTIAL_29_5));
|
||||||
|
this->command(0x24);
|
||||||
|
this->write_lut_(LUT_24_BB_PARTIAL_29_5, sizeof(LUT_24_BB_PARTIAL_29_5));
|
||||||
|
ESP_LOGD(TAG, "initialized partial update");
|
||||||
|
}
|
||||||
|
|
||||||
void HOT GDEW029T5::display() {
|
void HOT GDEW029T5::display() {
|
||||||
|
bool full_update = this->at_update_ == 0;
|
||||||
|
if (full_update) {
|
||||||
|
this->init_full_();
|
||||||
|
} else {
|
||||||
|
this->init_partial_();
|
||||||
|
this->command(0x91); // partial in
|
||||||
|
// set partial window
|
||||||
|
this->command(0x90);
|
||||||
|
// this->data(0);
|
||||||
|
this->data(0);
|
||||||
|
// this->data(0);
|
||||||
|
this->data((this->get_width_internal() - 1) % 256);
|
||||||
|
this->data(0);
|
||||||
|
this->data(0);
|
||||||
|
this->data(((this->get_height_internal() - 1)) / 256);
|
||||||
|
this->data(((this->get_height_internal() - 1)) % 256);
|
||||||
|
this->data(0x01);
|
||||||
|
}
|
||||||
|
// input old buffer data
|
||||||
|
this->command(0x10);
|
||||||
|
delay(2);
|
||||||
|
this->start_data_();
|
||||||
|
for (size_t i = 0; i < this->get_buffer_length_(); i++) {
|
||||||
|
this->write_byte(this->old_buffer_[i]);
|
||||||
|
}
|
||||||
|
this->end_data_();
|
||||||
|
delay(2);
|
||||||
|
|
||||||
// COMMAND DATA START TRANSMISSION 2 (B/W only)
|
// COMMAND DATA START TRANSMISSION 2 (B/W only)
|
||||||
this->command(0x13);
|
this->command(0x13);
|
||||||
delay(2);
|
delay(2);
|
||||||
this->start_data_();
|
this->start_data_();
|
||||||
for (size_t i = 0; i < this->get_buffer_length_(); i++) {
|
for (size_t i = 0; i < this->get_buffer_length_(); i++) {
|
||||||
this->write_byte(this->buffer_[i]);
|
this->write_byte(this->buffer_[i]);
|
||||||
|
this->old_buffer_[i] = this->buffer_[i];
|
||||||
}
|
}
|
||||||
this->end_data_();
|
this->end_data_();
|
||||||
delay(2);
|
delay(2);
|
||||||
@ -1660,10 +1922,28 @@ void HOT GDEW029T5::display() {
|
|||||||
delay(2);
|
delay(2);
|
||||||
this->wait_until_idle_();
|
this->wait_until_idle_();
|
||||||
|
|
||||||
// COMMAND POWER OFF
|
if (full_update) {
|
||||||
// NOTE: power off < deep sleep
|
ESP_LOGD(TAG, "full update done");
|
||||||
this->command(0x02);
|
} else {
|
||||||
|
this->command(0x92); // partial out
|
||||||
|
ESP_LOGD(TAG, "partial update done");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
|
||||||
|
// COMMAND deep sleep
|
||||||
|
this->deep_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDEW029T5::write_lut_(const uint8_t *lut, const uint8_t size) {
|
||||||
|
// COMMAND WRITE LUT REGISTER
|
||||||
|
this->start_data_();
|
||||||
|
for (uint8_t i = 0; i < size; i++)
|
||||||
|
this->write_byte(lut[i]);
|
||||||
|
this->end_data_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDEW029T5::set_full_update_every(uint32_t full_update_every) { this->full_update_every_ = full_update_every; }
|
||||||
|
|
||||||
int GDEW029T5::get_width_internal() { return 128; }
|
int GDEW029T5::get_width_internal() { return 128; }
|
||||||
int GDEW029T5::get_height_internal() { return 296; }
|
int GDEW029T5::get_height_internal() { return 296; }
|
||||||
void GDEW029T5::dump_config() {
|
void GDEW029T5::dump_config() {
|
||||||
@ -1672,6 +1952,7 @@ void GDEW029T5::dump_config() {
|
|||||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
LOG_PIN(" DC Pin: ", this->dc_pin_);
|
||||||
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
LOG_PIN(" Busy Pin: ", this->busy_pin_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Full Update Every: %" PRIu32, this->full_update_every_);
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,16 +254,27 @@ class GDEW029T5 : public WaveshareEPaper {
|
|||||||
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
void deep_sleep() override {
|
void deep_sleep() override;
|
||||||
// COMMAND DEEP SLEEP
|
void set_full_update_every(uint32_t full_update_every);
|
||||||
this->command(0x07);
|
|
||||||
this->data(0xA5); // check byte
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void init_display_();
|
||||||
|
void init_full_();
|
||||||
|
void init_partial_();
|
||||||
|
void write_lut_(const uint8_t *lut, uint8_t size);
|
||||||
|
void power_off_();
|
||||||
|
void power_on_();
|
||||||
int get_width_internal() override;
|
int get_width_internal() override;
|
||||||
|
|
||||||
int get_height_internal() override;
|
int get_height_internal() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t full_update_every_{30};
|
||||||
|
uint32_t at_update_{0};
|
||||||
|
bool deep_sleep_between_updates_{false};
|
||||||
|
bool power_is_on_{false};
|
||||||
|
bool is_deep_sleep_{false};
|
||||||
|
uint8_t *old_buffer_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
class WaveshareEPaper2P7InV2 : public WaveshareEPaper {
|
class WaveshareEPaper2P7InV2 : public WaveshareEPaper {
|
||||||
@ -416,6 +427,26 @@ class WaveshareEPaper2P9InDKE : public WaveshareEPaper {
|
|||||||
int get_height_internal() override;
|
int get_height_internal() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WaveshareEPaper2P9InD : public WaveshareEPaper {
|
||||||
|
public:
|
||||||
|
void initialize() override;
|
||||||
|
|
||||||
|
void display() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void deep_sleep() override {
|
||||||
|
// COMMAND DEEP SLEEP
|
||||||
|
this->command(0x07);
|
||||||
|
this->data(0xA5);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int get_width_internal() override;
|
||||||
|
|
||||||
|
int get_height_internal() override;
|
||||||
|
};
|
||||||
|
|
||||||
class WaveshareEPaper4P2In : public WaveshareEPaper {
|
class WaveshareEPaper4P2In : public WaveshareEPaper {
|
||||||
public:
|
public:
|
||||||
void initialize() override;
|
void initialize() override;
|
||||||
|
@ -459,6 +459,7 @@ display:
|
|||||||
reset_pin:
|
reset_pin:
|
||||||
allow_other_uses: true
|
allow_other_uses: true
|
||||||
number: ${reset_pin}
|
number: ${reset_pin}
|
||||||
|
full_update_every: 30
|
||||||
lambda: |-
|
lambda: |-
|
||||||
it.rectangle(0, 0, it.get_width(), it.get_height());
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
@ -713,6 +714,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
|
||||||
|
model: 2.90in-d
|
||||||
|
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}
|
||||||
|
reset_duration: 200ms
|
||||||
|
lambda: |-
|
||||||
|
it.rectangle(0, 0, it.get_width(), it.get_height());
|
||||||
|
|
||||||
- platform: waveshare_epaper
|
- platform: waveshare_epaper
|
||||||
model: 2.90in
|
model: 2.90in
|
||||||
spi_id: spi_waveshare_epaper
|
spi_id: spi_waveshare_epaper
|
||||||
|
Loading…
x
Reference in New Issue
Block a user