ESPHome 2025.5.0
Loading...
Searching...
No Matches
waveshare_213v3.cpp
Go to the documentation of this file.
1#include "waveshare_epaper.h"
2#include "esphome/core/log.h"
4
5namespace esphome {
6namespace waveshare_epaper {
7
8static const char *const TAG = "waveshare_2.13v3";
9
10static const uint8_t PARTIAL_LUT[] = {
11 0x32, // cmd
12 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
13 0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0,
14 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
15 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
16 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
17 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
18 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
19 0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
20};
21
22static const uint8_t FULL_LUT[] = {
23 0x32, // CMD
24 0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x4A, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
25 0x0, 0x0, 0x0, 0x0, 0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x4A, 0x80, 0x0,
26 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
27 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, 0xF, 0x0, 0x0, 0x2, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0,
28 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
29 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
30 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
31 0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0,
32};
33
34static const uint8_t SW_RESET = 0x12;
35static const uint8_t ACTIVATE = 0x20;
36static const uint8_t WRITE_BUFFER = 0x24;
37static const uint8_t WRITE_BASE = 0x26;
38
39static const uint8_t DRV_OUT_CTL[] = {0x01, 0x27, 0x01, 0x00}; // driver output control
40static const uint8_t GATEV[] = {0x03, 0x17};
41static const uint8_t SRCV[] = {0x04, 0x41, 0x0C, 0x32};
42static const uint8_t SLEEP[] = {0x10, 0x01};
43static const uint8_t DATA_ENTRY[] = {0x11, 0x03}; // data entry mode
44static const uint8_t TEMP_SENS[] = {0x18, 0x80}; // Temp sensor
45static const uint8_t DISPLAY_UPDATE[] = {0x21, 0x00, 0x80}; // Display update control
46static const uint8_t UPSEQ[] = {0x22, 0xC0};
47static const uint8_t ON_FULL[] = {0x22, 0xC7};
48static const uint8_t ON_PARTIAL[] = {0x22, 0x0F};
49static const uint8_t VCOM[] = {0x2C, 0x36};
50static const uint8_t CMD5[] = {0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00};
51static const uint8_t BORDER_PART[] = {0x3C, 0x80}; // border waveform
52static const uint8_t BORDER_FULL[] = {0x3C, 0x05}; // border waveform
53static const uint8_t CMD1[] = {0x3F, 0x22};
54static const uint8_t RAM_X_START[] = {0x44, 0x00, 121 / 8}; // set ram_x_address_start_end
55static const uint8_t RAM_Y_START[] = {0x45, 0x00, 0x00, 250 - 1, 0}; // set ram_y_address_start_end
56static const uint8_t RAM_X_POS[] = {0x4E, 0x00}; // set ram_x_address_counter
57// static const uint8_t RAM_Y_POS[] = {0x4F, 0x00, 0x00}; // set ram_y_address_counter
58#define SEND(x) this->cmd_data(x, sizeof(x))
59
60void WaveshareEPaper2P13InV3::write_lut_(const uint8_t *lut) {
61 this->wait_until_idle_();
62 this->cmd_data(lut, sizeof(PARTIAL_LUT));
63 SEND(CMD1);
64 SEND(GATEV);
65 SEND(SRCV);
66 SEND(VCOM);
67}
68
69// write the buffer starting on line top, up to line bottom.
70void WaveshareEPaper2P13InV3::write_buffer_(uint8_t cmd, int top, int bottom) {
71 this->wait_until_idle_();
72 this->set_window_(top, bottom);
73 this->command(cmd);
74 this->start_data_();
75
76 auto width_bytes = this->get_width_controller() / 8;
77 this->write_array(this->buffer_ + top * width_bytes, (bottom - top) * width_bytes);
78 this->end_data_();
79}
80
82 if (this->reset_pin_ != nullptr) {
83 this->reset_pin_->digital_write(false);
84 delay(2);
85 this->reset_pin_->digital_write(true);
86 }
87}
88
91 this->setup_pins_();
92 this->spi_setup();
93 this->reset_();
94
95 delay(20);
96 this->send_reset_();
97 // as a one-off delay this is not worth working around.
98 delay(100); // NOLINT
99 this->wait_until_idle_();
100 this->command(SW_RESET);
101 this->wait_until_idle_();
102
103 SEND(DRV_OUT_CTL);
104 SEND(DATA_ENTRY);
105 SEND(CMD5);
106 this->set_window_(0, this->get_height_internal());
107 SEND(BORDER_FULL);
108 SEND(DISPLAY_UPDATE);
109 SEND(TEMP_SENS);
110 this->wait_until_idle_();
111 this->write_lut_(FULL_LUT);
112}
113
114// t and b are y positions, i.e. line numbers.
116 uint8_t buffer[3];
117
118 SEND(RAM_X_START);
119 SEND(RAM_Y_START);
120 SEND(RAM_X_POS);
121 buffer[0] = 0x4F;
122 buffer[1] = (uint8_t) t;
123 buffer[2] = (uint8_t) (t >> 8);
124 SEND(buffer);
125}
126
127// must implement, but we override setup to have more control
129
131 this->send_reset_();
132 this->set_timeout(100, [this] {
133 this->write_lut_(PARTIAL_LUT);
134 SEND(BORDER_PART);
135 SEND(UPSEQ);
136 this->command(ACTIVATE);
137 this->set_timeout(100, [this] {
138 this->wait_until_idle_();
139 this->write_buffer_(WRITE_BUFFER, 0, this->get_height_internal());
140 SEND(ON_PARTIAL);
141 this->command(ACTIVATE); // Activate Display Update Sequence
142 this->is_busy_ = false;
143 });
144 });
145}
146
148 ESP_LOGI(TAG, "Performing full e-paper update.");
149 this->write_lut_(FULL_LUT);
150 this->write_buffer_(WRITE_BUFFER, 0, this->get_height_internal());
151 this->write_buffer_(WRITE_BASE, 0, this->get_height_internal());
152 SEND(ON_FULL);
153 this->command(ACTIVATE); // don't wait here
154 this->is_busy_ = false;
155}
156
158 if (this->is_busy_ || (this->busy_pin_ != nullptr && this->busy_pin_->digital_read()))
159 return;
160 this->is_busy_ = true;
161 const bool partial = this->at_update_ != 0;
162 this->at_update_ = (this->at_update_ + 1) % this->full_update_every_;
163 if (partial) {
164 this->partial_update_();
165 } else {
166 this->full_update_();
167 }
168}
169
172
174
175uint32_t WaveshareEPaper2P13InV3::idle_timeout_() { return 5000; }
176
178 LOG_DISPLAY("", "Waveshare E-Paper", this)
179 ESP_LOGCONFIG(TAG, " Model: 2.13inV3");
180 LOG_PIN(" CS Pin: ", this->cs_)
181 LOG_PIN(" Reset Pin: ", this->reset_pin_)
182 LOG_PIN(" DC Pin: ", this->dc_pin_)
183 LOG_PIN(" Busy Pin: ", this->busy_pin_)
184 LOG_UPDATE_INTERVAL(this)
185}
186
187void WaveshareEPaper2P13InV3::set_full_update_every(uint32_t full_update_every) {
188 this->full_update_every_ = full_update_every;
189}
190
191} // namespace waveshare_epaper
192} // namespace esphome
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.cpp:72
virtual void digital_write(bool value)=0
virtual bool digital_read()=0
void init_internal_(uint32_t buffer_length)
void set_full_update_every(uint32_t full_update_every)
void write_buffer_(uint8_t cmd, int top, int bottom)
void cmd_data(const uint8_t *data, size_t length)
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:28