ESPHome 2026.10.0
Loading...
Searching...
No Matches
epaper_spi_ssd1677.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4
6#include "esphome/core/log.h"
7
8namespace esphome::epaper_spi {
9static constexpr const char *const TAG = "epaper_spi.ssd1677";
10
13 if (!this->is_failed())
15}
16
18 if (!this->is_using_partial_update_())
19 return;
20 if (!this->sent_.init(this->plane_row_length_() * this->height_)) {
21 ESP_LOGW(TAG, "No memory for the comparison frame; partial updates will degrade unchanged areas");
22 }
23}
24
25void EPaperSSD1677::plane_row(size_t y, uint8_t *out) {
26 const size_t row_length = this->plane_row_length_();
27 const size_t data_idx = y * row_length;
28 for (size_t i = 0; i != row_length; i++)
29 out[i] = this->buffer_[data_idx + i];
30}
31
32// Nothing a partial update needs is kept in controller RAM any more, so skip the reset for those.
34 if (this->update_count_ != 0 && this->sent_.is_valid())
35 return true;
36 return EPaperMono::reset();
37}
38
39// The window always covers the whole panel, so each plane is the frame's bytes in order. Where
40// those bytes are already stored as the plane needs them (the comparison frame, and a 1-bit
41// buffer) they are written straight from the buffer, as many at a time as the time slice allows;
42// otherwise they are built a row at a time by plane_row().
44 if (!this->sent_.is_valid())
46
47 const auto start_time = millis();
48 if (this->current_data_index_ == 0) {
49 if (this->plane_ == 0) {
50 this->x_low_ = 0;
51 this->x_high_ = this->width_;
52 this->y_low_ = 0;
53 this->y_high_ = this->height_;
54 }
55 this->set_window();
56 this->command(this->plane_ == 0 ? 0x26 : 0x24);
57 }
58 // A full update ignores 0x26, and the copy may not hold a real frame yet (first update after
59 // boot): send the new frame to both planes.
60 const bool send_copy = this->plane_ == 0 && this->update_count_ != 0;
61 const bool direct = send_copy || this->buffer_is_plane();
62 const auto &source = send_copy ? this->sent_ : this->buffer_;
63 const size_t row_length = this->plane_row_length_();
64 const size_t plane_length = row_length * this->height_;
65 // Roughly what the bus moves in one time slice, so a slice is not overrun by much
66 const size_t max_chunk = std::max<size_t>(this->data_rate_ / 8000 * MAX_TRANSFER_TIME, MAX_TRANSFER_SIZE);
67 SmallBufferWithHeapFallback<128> row_alloc(direct ? 0 : row_length);
68 this->start_data_();
69 while (this->current_data_index_ != plane_length) {
70 size_t length;
71 const uint8_t *data;
72 if (direct) {
73 data = source.get_span(this->current_data_index_, length);
74 length = std::min(length, max_chunk);
75 } else {
76 // Always at the start of a row here, since this path sends whole rows only
77 this->plane_row(this->current_data_index_ / row_length, row_alloc.get());
78 data = row_alloc.get();
79 length = row_length;
80 }
81 this->write_array(data, length);
82 if (this->plane_ == 1)
83 this->sent_.write(this->current_data_index_, data, length);
85 if (this->current_data_index_ != plane_length && millis() - start_time > MAX_TRANSFER_TIME) {
86 // Let the main loop run and come back next loop
87 this->disable();
88 return false;
89 }
90 }
91 this->disable();
92 this->current_data_index_ = 0;
93 if (this->plane_ == 0) {
94 this->plane_ = 1;
95 return false;
96 }
97 this->plane_ = 0;
98 return true;
99}
100
101} // namespace esphome::epaper_spi
bool is_failed() const
Definition component.h:272
Helper class for efficient buffer allocation - uses stack for small sizes, heap for large This is use...
Definition helpers.h:824
void command(uint8_t value)
split_buffer::SplitBuffer buffer_
Definition epaper_spi.h:174
virtual void plane_row(size_t y, uint8_t *out)
uint32_t data_rate_
Definition spi.h:430
bool init(size_t total_length, size_t max_buffer_size=SIZE_MAX)
void write(size_t index, const uint8_t *data, size_t length)
std::vector< uint8_t > & out
Definition gif.cpp:49
uint32_t IRAM_ATTR HOT millis()
Definition hal.cpp:25
uint16_t length
Definition tt21100.cpp:0
uint16_t y
Definition tt21100.cpp:6