#include "epaper_spi_mono.h" #include #include "esphome/core/log.h" namespace esphome::epaper_spi { static constexpr const char *const TAG = "epaper_spi.mono"; void EPaperMono::refresh_screen(bool partial) { ESP_LOGV(TAG, "Refresh screen"); this->cmd_data(0x22, {partial ? (uint8_t) 0xFF : (uint8_t) 0xF7}); this->command(0x20); } void EPaperMono::deep_sleep() { ESP_LOGV(TAG, "Deep sleep"); if (this->is_using_partial_update_()) { this->cmd_data(0x10, {0x00}); // sleep in power on mode } else { this->cmd_data(0x10, {0x03}); // deep sleep } } bool EPaperMono::reset() { if (EPaperBase::reset()) { this->command(0x12); return true; } return false; } void EPaperMono::set_window() { // if not using partial update, the display will go into deep sleep, so must rewrite entire // buffer since the display RAM will not retain contents if (!this->is_using_partial_update_()) { this->x_low_ = 0; this->x_high_ = this->width_; this->y_low_ = 0; this->y_high_ = this->height_; } // round x-coordinates to byte boundaries this->x_low_ &= ~7; this->x_high_ += 7; this->x_high_ &= ~7; this->cmd_data(0x44, {(uint8_t) this->x_low_, (uint8_t) (this->x_low_ / 256), (uint8_t) (this->x_high_ - 1), (uint8_t) ((this->x_high_ - 1) / 256)}); this->cmd_data(0x4E, {(uint8_t) this->x_low_, (uint8_t) (this->x_low_ / 256)}); this->cmd_data(0x45, {(uint8_t) this->y_low_, (uint8_t) (this->y_low_ / 256), (uint8_t) (this->y_high_ - 1), (uint8_t) ((this->y_high_ - 1) / 256)}); this->cmd_data(0x4F, {(uint8_t) this->y_low_, (uint8_t) (this->y_low_ / 256)}); } bool HOT EPaperMono::transfer_data() { auto start_time = millis(); if (this->current_data_index_ == 0) { // round to byte boundaries this->set_window(); // for monochrome, we still need to clear the red data buffer at least once to prevent it // causing dirty pixels after partial refresh. this->command(this->send_red_ ? 0x26 : 0x24); this->current_data_index_ = this->y_low_; // actually current line } size_t row_length = (this->x_high_ - this->x_low_) / 8; FixedVector bytes_to_send{}; bytes_to_send.init(row_length); ESP_LOGV(TAG, "Writing %u bytes at line %zu at %ums", row_length, this->current_data_index_, (unsigned) millis()); this->start_data_(); while (this->current_data_index_ != this->y_high_) { size_t data_idx = this->current_data_index_ * this->row_width_ + this->x_low_ / 8; for (size_t i = 0; i != row_length; i++) { bytes_to_send[i] = this->send_red_ ? 0 : this->buffer_[data_idx++]; } ++this->current_data_index_; this->write_array(&bytes_to_send.front(), row_length); // NOLINT if (millis() - start_time > MAX_TRANSFER_TIME) { // Let the main loop run and come back next loop this->disable(); return false; } } this->disable(); this->current_data_index_ = 0; if (this->send_red_) { this->send_red_ = false; return false; } return true; } } // namespace esphome::epaper_spi