ESPHome 2025.12.3
Loading...
Searching...
No Matches
epaper_spi.h
Go to the documentation of this file.
1#pragma once
2
7
8namespace esphome::epaper_spi {
9using namespace display;
10
11enum class EPaperState : uint8_t {
12 IDLE, // not doing anything
13 UPDATE, // update the buffer
14 RESET, // drive reset low (active)
15 RESET_END, // drive reset high (inactive)
16
17 SHOULD_WAIT, // states higher than this should wait for the display to be not busy
18 INITIALISE, // send the init sequence
19 TRANSFER_DATA, // transfer data to the display
20 POWER_ON, // power on the display
21 REFRESH_SCREEN, // send refresh command
22 POWER_OFF, // power off the display
23 DEEP_SLEEP, // deep sleep the display
24};
25
26static constexpr uint8_t NONE = 0;
27static constexpr uint8_t MIRROR_X = 1;
28static constexpr uint8_t MIRROR_Y = 2;
29static constexpr uint8_t SWAP_XY = 4;
30
31static constexpr uint32_t MAX_TRANSFER_TIME = 10; // Transfer in 10ms blocks to allow the loop to run
32static constexpr size_t MAX_TRANSFER_SIZE = 128;
33static constexpr uint8_t DELAY_FLAG = 0xFF;
34
35class EPaperBase : public Display,
36 public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
37 spi::DATA_RATE_2MHZ> {
38 public:
39 EPaperBase(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence,
40 size_t init_sequence_length, DisplayType display_type = DISPLAY_TYPE_BINARY)
41 : name_(name),
42 width_(width),
43 height_(height),
44 init_sequence_(init_sequence),
45 init_sequence_length_(init_sequence_length),
46 display_type_(display_type) {}
47 void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; }
48 float get_setup_priority() const override;
50 void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; }
51 void set_reset_duration(uint32_t reset_duration) { this->reset_duration_ = reset_duration; }
52 void set_transform(uint8_t transform) { this->transform_ = transform; }
53 void set_full_update_every(uint8_t full_update_every) { this->full_update_every_ = full_update_every; }
54 void dump_config() override;
55
56 void command(uint8_t value);
57 void data(uint8_t value);
58 void cmd_data(uint8_t command, const uint8_t *ptr, size_t length);
59
60 void update() override;
61 void loop() override;
62
63 void setup() override;
64
65 void on_safe_shutdown() override;
66
67 DisplayType get_display_type() override { return this->display_type_; };
68
69 // Default implementations for monochrome displays
70 static uint8_t color_to_bit(Color color) {
71 // It's always a shade of gray. Map to BLACK or WHITE.
72 // We split the luminance at a suitable point
73 if ((static_cast<int>(color.r) + color.g + color.b) > 512) {
74 return 1;
75 }
76 return 0;
77 }
78 void fill(Color color) override {
79 auto pixel_color = color_to_bit(color) ? 0xFF : 0x00;
80
81 // We store 8 pixels per byte
82 this->buffer_.fill(pixel_color);
83 this->x_high_ = this->width_;
84 this->y_high_ = this->height_;
85 this->x_low_ = 0;
86 this->y_low_ = 0;
87 }
88
89 void clear() override {
90 // clear buffer to white, just like real paper.
91 this->fill(COLOR_ON);
92 }
93
94 protected:
95 int get_height_internal() override { return this->height_; };
96 int get_width_internal() override { return this->width_; };
97 int get_width() override { return this->transform_ & SWAP_XY ? this->height_ : this->width_; }
98 int get_height() override { return this->transform_ & SWAP_XY ? this->width_ : this->height_; }
99 void draw_pixel_at(int x, int y, Color color) override;
100 void process_state_();
101
102 const char *epaper_state_to_string_();
103 bool is_idle_() const;
104 void setup_pins_() const;
105 virtual bool reset();
106 void initialise_();
107 void wait_for_idle_(bool should_wait);
108 bool init_buffer_(size_t buffer_length);
109 bool rotate_coordinates_(int &x, int &y);
110
118 virtual bool transfer_data() = 0;
122 virtual void refresh_screen(bool partial) = 0;
123
127 virtual void power_on() = 0;
131 virtual void power_off() = 0;
132
136 virtual void deep_sleep() = 0;
137
138 void set_state_(EPaperState state, uint16_t delay = 0);
139
140 void start_command_();
141 void end_command_();
142 void start_data_();
143 void end_data_();
144
145 // properties initialised in the constructor
146 const char *name_;
147 uint16_t width_;
148 uint16_t height_;
149 const uint8_t *init_sequence_;
152
154 size_t current_data_index_{}; // used by data transfer to track progress
160 uint32_t delay_until_{};
161 uint8_t transform_{};
162 uint8_t update_count_{};
163 // these values represent the bounds of the updated buffer. Note that x_high and y_high
164 // point to the pixel past the last one updated, i.e. may range up to width/height.
165 uint16_t x_low_{}, y_low_{}, x_high_{}, y_high_{};
166
167#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
170#endif
171#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
173#endif
174
175 // properties with specific initialisers go last
177 uint32_t reset_duration_{10};
179};
180
181} // namespace esphome::epaper_spi
virtual void power_off()=0
Power the display off.
void command(uint8_t value)
void set_transform(uint8_t transform)
Definition epaper_spi.h:52
void fill(Color color) override
Definition epaper_spi.h:78
void process_state_()
Process the state machine.
virtual void deep_sleep()=0
Place the display into deep sleep.
int get_height_internal() override
Definition epaper_spi.h:95
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.
void set_dc_pin(GPIOPin *dc_pin)
Definition epaper_spi.h:47
void set_reset_pin(GPIOPin *reset)
Definition epaper_spi.h:49
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:155
void cmd_data(uint8_t command, const uint8_t *ptr, size_t length)
void set_state_(EPaperState state, uint16_t delay=0)
const char * epaper_state_to_string_()
virtual void power_on()=0
Power the display on.
void set_reset_duration(uint32_t reset_duration)
Definition epaper_spi.h:51
void set_full_update_every(uint8_t full_update_every)
Definition epaper_spi.h:53
DisplayType get_display_type() override
Definition epaper_spi.h:67
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:50
int get_width_internal() override
Definition epaper_spi.h:96
static uint8_t color_to_bit(Color color)
Definition epaper_spi.h:70
EPaperBase(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, size_t init_sequence_length, DisplayType display_type=DISPLAY_TYPE_BINARY)
Definition epaper_spi.h:39
The SPIDevice is what components using the SPI will create.
Definition spi.h:427
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:0
const Color COLOR_ON(255, 255, 255, 255)
Turn the pixel ON.
Definition display.h:303
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:31
uint8_t g
Definition color.h:34
uint8_t b
Definition color.h:38
uint8_t r
Definition color.h:30
uint16_t length
Definition tt21100.cpp:0
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6