ESPHome 2026.10.2
Loading...
Searching...
No Matches
epaper_spi.h
Go to the documentation of this file.
1#pragma once
2
3#include "colorconv.h"
8
9namespace esphome::epaper_spi {
10using namespace display;
11
12enum class EPaperState : uint8_t {
13 IDLE, // not doing anything
14 UPDATE, // update the buffer
15 RESET, // drive reset low (active)
16 RESET_END, // drive reset high (inactive)
17
18 SHOULD_WAIT, // states higher than this should wait for the display to be not busy
19 INITIALISE, // send the init sequence
20 TRANSFER_DATA, // transfer data to the display
21 POWER_ON, // power on the display
22 REFRESH_SCREEN, // send refresh command
23 POWER_OFF, // power off the display
24 DEEP_SLEEP, // deep sleep the display
25};
26
27static constexpr uint8_t NONE = 0;
28static constexpr uint8_t MIRROR_X = 1;
29static constexpr uint8_t MIRROR_Y = 2;
30static constexpr uint8_t SWAP_XY = 4;
31
32static constexpr uint32_t MAX_TRANSFER_TIME = 10; // Transfer in 10ms blocks to allow the loop to run
33static constexpr size_t MAX_TRANSFER_SIZE = 128;
34static constexpr uint8_t DELAY_FLAG = 0xFF;
35
36class EPaperBase : public Display,
37 public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
38 spi::DATA_RATE_2MHZ> {
39 public:
40 EPaperBase(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence = nullptr,
41 size_t init_sequence_length = 0, DisplayType display_type = DISPLAY_TYPE_BINARY)
42 : name_(name),
43 width_(width),
44 height_(height),
45 init_sequence_(init_sequence),
46 init_sequence_length_(init_sequence_length),
47 display_type_(display_type) {
48 this->row_width_ = (this->width_ + 7) / 8; // width of a row in bytes
49 }
50 void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; }
51 float get_setup_priority() const override;
53 void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; }
54 void set_enable_pins(std::vector<GPIOPin *> enable_pins) { this->enable_pins_ = std::move(enable_pins); }
55 void set_reset_duration(uint32_t reset_duration) { this->reset_duration_ = reset_duration; }
56 void set_transform(uint8_t transform) {
57 this->transform_ = transform;
59 }
60 void set_rotation(DisplayRotation rotation) override {
61 Display::set_rotation(rotation);
63 }
64 void set_full_update_every(uint8_t full_update_every) { this->full_update_every_ = full_update_every; }
65 void dump_config() override;
66
67 void command(uint8_t value);
68 void cmd_data(uint8_t command, const uint8_t *ptr, size_t length);
69
70 // variant with in-place initializer list
71 void cmd_data(uint8_t command, std::initializer_list<uint8_t> data) {
72 this->cmd_data(command, data.begin(), data.size());
73 }
74
75 void update() override;
76 void loop() override;
77
78 void setup() override;
79
80 void on_safe_shutdown() override;
81
82 DisplayType get_display_type() override { return this->display_type_; };
83
84 // Default implementation for monochrome displays
85 void fill(Color color) override {
86 // If clipping is active, fall back to base implementation
87 if (this->get_clipping().is_set()) {
88 Display::fill(color);
89 return;
90 }
91
92 auto pixel_color = color_to_mono(color) ? 0xFF : 0x00;
93
94 // We store 8 pixels per byte
95 this->buffer_.fill(pixel_color);
96 this->x_high_ = this->width_;
97 this->y_high_ = this->height_;
98 this->x_low_ = 0;
99 this->y_low_ = 0;
100 }
101
102 void clear() override {
103 // clear buffer to white, just like real paper.
104 this->fill(COLOR_ON);
105 }
106
107 int get_width() override { return this->effective_transform_ & SWAP_XY ? this->height_ : this->width_; }
108 int get_height() override { return this->effective_transform_ & SWAP_XY ? this->width_ : this->height_; }
109 void draw_pixel_at(int x, int y, Color color) override;
110 // Make the next update a full one. Applied when that update starts, so one in progress is not affected.
112 // True from the start of an update until the display has refreshed and gone back to sleep.
113 bool is_updating() const { return this->state_ != EPaperState::IDLE; }
114
115 protected:
116 int get_height_internal() override { return this->height_; };
117 int get_width_internal() override { return this->width_; };
118 bool is_using_partial_update_() const { return this->full_update_every_ > 1; }
119 void process_state_();
120
121 const char *epaper_state_to_string_();
122 bool is_idle_() const;
123 void setup_pins_() const;
124 virtual bool reset();
125 virtual bool initialise(bool partial);
126 void send_init_sequence_(const uint8_t *sequence, size_t length);
127 void wait_for_idle_(bool should_wait);
128 bool init_buffer_(size_t buffer_length);
130 bool rotate_coordinates_(int &x, int &y);
131
139 virtual bool transfer_data() = 0;
143 virtual void refresh_screen(bool partial) = 0;
144
148 virtual void power_on() = 0;
152 virtual void power_off() = 0;
153
157 virtual void deep_sleep() = 0;
158
159 void set_state_(EPaperState state, uint16_t delay = 0);
160
161 void start_data_();
162
163 // properties initialised in the constructor
164 const char *name_;
165 uint16_t width_;
166 uint16_t row_width_; // width of a row in bytes
167 uint16_t height_;
168 const uint8_t *init_sequence_;
171
173 size_t current_data_index_{}; // used by data transfer to track progress
178 std::vector<GPIOPin *> enable_pins_{};
180 uint32_t delay_until_{}; // timestamp until which to delay processing
181 uint16_t next_delay_{}; // milliseconds to delay before next state
182 uint8_t transform_{};
184 uint8_t update_count_{};
186 // these values represent the bounds of the updated buffer. Note that x_high and y_high
187 // point to the pixel past the last one updated, i.e. may range up to width/height.
188 uint16_t x_low_{}, y_low_{}, x_high_{}, y_high_{};
189
190#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
193#endif
194#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
196#endif
197
198 // properties with specific initialisers go last
202};
203
204} // namespace esphome::epaper_spi
virtual void fill(Color color)
Fill the entire screen with the given color.
Definition display.cpp:15
virtual void set_rotation(DisplayRotation rotation)
Internal method to set the display rotation with.
Definition display.cpp:17
Rect get_clipping() const
Get the current the clipping rectangle.
Definition display.cpp:764
virtual void power_off()=0
Power the display off.
void command(uint8_t value)
void set_rotation(DisplayRotation rotation) override
Definition epaper_spi.h:60
void set_enable_pins(std::vector< GPIOPin * > enable_pins)
Definition epaper_spi.h:54
void set_transform(uint8_t transform)
Definition epaper_spi.h:56
void fill(Color color) override
Definition epaper_spi.h:85
void process_state_()
Process the state machine.
virtual void deep_sleep()=0
Place the display into deep sleep.
void draw_pixel_at(int x, int y, Color color) override
Default implementation for monochrome displays where 8 pixels are packed to a byte.
bool rotate_coordinates_(int &x, int &y)
Check and rotate coordinates based on the transform flags.
void loop() override
Called during the loop task.
virtual void refresh_screen(bool partial)=0
Refresh the screen after data transfer.
virtual bool initialise(bool partial)
void set_dc_pin(GPIOPin *dc_pin)
Definition epaper_spi.h:50
void send_init_sequence_(const uint8_t *sequence, size_t length)
void set_reset_pin(GPIOPin *reset)
Definition epaper_spi.h:52
virtual bool transfer_data()=0
Methods that must be implemented by concrete classes to control the display.
split_buffer::SplitBuffer buffer_
Definition epaper_spi.h:174
void cmd_data(uint8_t command, const uint8_t *ptr, size_t length)
void cmd_data(uint8_t command, std::initializer_list< uint8_t > data)
Definition epaper_spi.h:71
void set_state_(EPaperState state, uint16_t delay=0)
const char * epaper_state_to_string_()
EPaperBase(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence=nullptr, size_t init_sequence_length=0, DisplayType display_type=DISPLAY_TYPE_BINARY)
Definition epaper_spi.h:40
virtual void power_on()=0
Power the display on.
void set_reset_duration(uint32_t reset_duration)
Definition epaper_spi.h:55
void set_full_update_every(uint8_t full_update_every)
Definition epaper_spi.h:64
DisplayType get_display_type() override
Definition epaper_spi.h:82
void wait_for_idle_(bool should_wait)
float get_setup_priority() const override
bool init_buffer_(size_t buffer_length)
void set_busy_pin(GPIOPin *busy)
Definition epaper_spi.h:53
std::vector< GPIOPin * > enable_pins_
Definition epaper_spi.h:178
The SPIDevice is what components using the SPI will create.
Definition spi.h:450
A SplitBuffer allocates a large memory buffer potentially as multiple smaller buffers to facilitate a...
void fill(uint8_t value) const
Fill the entire buffer with a single byte value.
bool state
Definition fan.h:2
constexpr Color COLOR_ON(255, 255, 255, 255)
Turn the pixel ON.
constexpr uint8_t color_to_mono(Color color)
Map RGB color to a single monochrome bit.
Definition colorconv.h:29
void HOT delay(uint32_t ms)
Definition hal.cpp:85
static void uint32_t
uint16_t length
Definition tt21100.cpp:0
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6