ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
epaper_waveshare_bwr.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4
5namespace esphome::epaper_spi {
6
7enum class BwrState : uint8_t {
10 BWR_RED,
11};
12
13static BwrState color_to_bwr(Color color) {
14 if (color.r > color.g + color.b && color.r > 127) {
15 return BwrState::BWR_RED;
16 }
17 if (color.r + color.g + color.b >= 382) {
19 }
21}
22
23// UC8179 3-color display buffer layout:
24// - 1 bit per pixel, 8 pixels per byte
25// - Buffer first half: Black/White plane (1=black, 0=white)
26// - Buffer second half: Red plane (1=red, 0=white)
27// - Total: row_width * height * 2 bytes
28
30 if (!this->rotate_coordinates_(x, y))
31 return;
32
33 const uint32_t pos = (x / 8) + (y * this->row_width_);
34 const uint8_t bit = 0x80 >> (x & 0x07);
35 const uint32_t red_offset = this->buffer_length_ / 2u;
36
37 const auto bwr = color_to_bwr(color);
38
39 if (bwr == BwrState::BWR_BLACK) {
40 this->buffer_[pos] |= bit;
41 } else {
42 this->buffer_[pos] &= ~bit;
43 }
44
45 if (bwr == BwrState::BWR_RED) {
46 this->buffer_[red_offset + pos] |= bit;
47 } else {
48 this->buffer_[red_offset + pos] &= ~bit;
49 }
50}
51
53 const size_t half_buffer = this->buffer_length_ / 2u;
54 const auto bwr = color_to_bwr(color);
55
56 if (bwr == BwrState::BWR_BLACK) {
57 // Black plane: 0xFF (black), Red plane: 0x00 (no red)
58 for (size_t i = 0; i < half_buffer; i++)
59 this->buffer_[i] = 0xFF;
60 for (size_t i = 0; i < half_buffer; i++)
61 this->buffer_[half_buffer + i] = 0x00;
62 } else if (bwr == BwrState::BWR_RED) {
63 // Black plane: 0x00 (no black), Red plane: 0xFF (red)
64 for (size_t i = 0; i < half_buffer; i++)
65 this->buffer_[i] = 0x00;
66 for (size_t i = 0; i < half_buffer; i++)
67 this->buffer_[half_buffer + i] = 0xFF;
68 } else {
69 // Black plane: 0x00 (no black), Red plane: 0x00 (no red)
70 this->buffer_.fill(0x00);
71 }
72}
73
75 const uint32_t start_time = millis();
76 const size_t buffer_length = this->buffer_length_;
77 const size_t half_buffer = buffer_length / 2u;
78
79 uint8_t bytes_to_send[MAX_TRANSFER_SIZE];
80
81 // Phase 1: send Black/White plane (first half) via command 0x10 (DTM1)
82 // UC8179 DTM1 (0x10): inverted to get 0=black, 1=white
83 if (this->current_data_index_ < half_buffer) {
84 if (this->current_data_index_ == 0) {
85 this->command(0x10); // DATA START TRANSMISSION 1 (black channel)
86 }
87 this->start_data_();
88 while (this->current_data_index_ < half_buffer) {
89 const size_t bytes_to_copy = std::min(MAX_TRANSFER_SIZE, half_buffer - this->current_data_index_);
90 for (size_t i = 0; i < bytes_to_copy; i++) {
91 bytes_to_send[i] = ~this->buffer_[this->current_data_index_ + i];
92 }
93 this->write_array(bytes_to_send, bytes_to_copy);
94 this->current_data_index_ += bytes_to_copy;
95 if (millis() - start_time > MAX_TRANSFER_TIME) {
96 this->disable();
97 return false;
98 }
99 }
100 this->disable();
101 }
102
103 // Phase 2: send Red plane (second half) via command 0x13 (DTM2)
104 // UC8179 DTM2 (0x13): 1=red, 0=white
105 if (this->current_data_index_ < buffer_length) {
106 if (this->current_data_index_ == half_buffer) {
107 this->command(0x13); // DATA START TRANSMISSION 2 (red channel)
108 }
109 this->start_data_();
110 while (this->current_data_index_ < buffer_length) {
111 const size_t bytes_to_copy = std::min(MAX_TRANSFER_SIZE, buffer_length - this->current_data_index_);
112 for (size_t i = 0; i < bytes_to_copy; i++) {
113 bytes_to_send[i] = this->buffer_[this->current_data_index_ + i];
114 }
115 this->write_array(bytes_to_send, bytes_to_copy);
116 this->current_data_index_ += bytes_to_copy;
117 if (millis() - start_time > MAX_TRANSFER_TIME) {
118 this->disable();
119 return false;
120 }
121 }
122 this->disable();
123 }
124
125 this->current_data_index_ = 0;
126 return true;
127}
128
130 this->cmd_data(0x01, {0x07, 0x17, 0x3F, 0x3F}); // POWER SETTING
131 this->command(0x04); // POWER ON
132}
133
135 this->command(0x12); // DISPLAY REFRESH
136}
137
139 this->command(0x02); // POWER OFF
140}
141
143 this->cmd_data(0x07, {0xA5}); // DEEP SLEEP with check code
144}
145
146} // namespace esphome::epaper_spi
void command(uint8_t value)
bool rotate_coordinates_(int &x, int &y)
Check and rotate coordinates based on the transform flags.
split_buffer::SplitBuffer buffer_
Definition epaper_spi.h:177
void cmd_data(uint8_t command, const uint8_t *ptr, size_t length)
void draw_pixel_at(int x, int y, Color color) override
void fill(uint8_t value) const
Fill the entire buffer with a single byte value.
constexpr NATIVE_COLOR color_to_bwr(Color color, NATIVE_COLOR hw_black, NATIVE_COLOR hw_white, NATIVE_COLOR hw_red)
Map RGB color to discrete BWR (black/white/red) 3 color key.
Definition colorconv.h:80
size_t size_t pos
Definition helpers.h:1052
uint32_t IRAM_ATTR HOT millis()
Definition hal.cpp:28
static void uint32_t
uint8_t g
Definition color.h:34
uint8_t b
Definition color.h:38
uint8_t r
Definition color.h:30
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6