ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
st7701s.cpp
Go to the documentation of this file.
1#ifdef USE_ESP32_VARIANT_ESP32S3
2#include "st7701s.h"
3#include "esphome/core/gpio.h"
4#include "esphome/core/log.h"
5#include <driver/gpio.h>
6
7namespace esphome::st7701s {
8
10 this->spi_setup();
12
13 esp_lcd_rgb_panel_config_t config{};
14 config.flags.fb_in_psram = 1;
15 config.bounce_buffer_size_px = this->width_ * 10;
16 config.num_fbs = 1;
17 config.timings.h_res = this->width_;
18 config.timings.v_res = this->height_;
19 config.timings.hsync_pulse_width = this->hsync_pulse_width_;
20 config.timings.hsync_back_porch = this->hsync_back_porch_;
21 config.timings.hsync_front_porch = this->hsync_front_porch_;
22 config.timings.vsync_pulse_width = this->vsync_pulse_width_;
23 config.timings.vsync_back_porch = this->vsync_back_porch_;
24 config.timings.vsync_front_porch = this->vsync_front_porch_;
25 config.timings.flags.pclk_active_neg = this->pclk_inverted_;
26 config.timings.pclk_hz = this->pclk_frequency_;
27 config.clk_src = LCD_CLK_SRC_PLL160M;
28 size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]);
29 for (size_t i = 0; i != data_pin_count; i++) {
30 config.data_gpio_nums[i] = static_cast<gpio_num_t>(this->data_pins_[i]->get_pin());
31 }
32 config.data_width = data_pin_count;
33 config.disp_gpio_num = GPIO_NUM_NC;
34 config.hsync_gpio_num = static_cast<gpio_num_t>(this->hsync_pin_->get_pin());
35 config.vsync_gpio_num = static_cast<gpio_num_t>(this->vsync_pin_->get_pin());
36 config.de_gpio_num = static_cast<gpio_num_t>(this->de_pin_->get_pin());
37 config.pclk_gpio_num = static_cast<gpio_num_t>(this->pclk_pin_->get_pin());
38 esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_);
39 if (err != ESP_OK) {
40 esph_log_e(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err));
41 this->mark_failed();
42 return;
43 }
44 ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_));
45 ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_));
46}
47
49 if (this->handle_ != nullptr)
50 esp_lcd_rgb_panel_restart(this->handle_);
51}
52
53void ST7701S::draw_pixels_internal(int x_start, int y_start, int w, int h, const uint8_t *ptr,
54 display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset,
55 int x_pad) {
56 if (w <= 0 || h <= 0)
57 return;
59 this->is_clipping()) {
61 return;
62 }
63 this->write_to_display_(x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad);
64}
65
66void ST7701S::write_to_display_(int x_start, int y_start, int w, int h, const uint8_t *ptr, int x_offset, int y_offset,
67 int x_pad) {
68 x_start += this->offset_x_;
69 y_start += this->offset_y_;
70 esp_err_t err;
71 // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display.
72 if (x_offset == 0 && x_pad == 0 && y_offset == 0) {
73 // we could deal here with a non-zero y_offset, but if x_offset is zero, y_offset probably will be so don't bother
74 err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y_start, x_start + w, y_start + h, ptr);
75 } else {
76 // draw line by line
77 auto stride = x_offset + w + x_pad;
78 for (int y = 0; y != h; y++) {
79 err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y + y_start, x_start + w, y + y_start + 1,
80 ptr + ((y + y_offset) * stride + x_offset) * 2);
81 if (err != ESP_OK)
82 break;
83 }
84 }
85 if (err != ESP_OK) {
86 esph_log_e(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err));
87 }
88}
89
90void ST7701S::draw_pixel_at(int x, int y, Color color) {
91 if (this->is_point_clipped(x, y))
92 return; // NOLINT
93
94 switch (this->rotation_) {
96 break;
98 std::swap(x, y);
99 x = this->width_ - x - 1;
100 break;
102 x = this->width_ - x - 1;
103 y = this->height_ - y - 1;
104 break;
106 std::swap(x, y);
107 y = this->height_ - y - 1;
108 break;
109 }
110 auto pixel = convert_big_endian(display::ColorUtil::color_to_565(color));
111
112 this->write_to_display_(x, y, 1, 1, (const uint8_t *) &pixel, 0, 0, 0);
113 this->feed_wdt_per_pixel_();
114}
115
116void ST7701S::write_command_(uint8_t value) {
117 this->enable();
118 if (this->dc_pin_ == nullptr) {
119 this->write(value, 9);
120 } else {
121 this->dc_pin_->digital_write(false);
122 this->write_byte(value);
123 this->dc_pin_->digital_write(true);
124 }
125 this->disable();
126}
127
128void ST7701S::write_data_(uint8_t value) {
129 this->enable();
130 if (this->dc_pin_ == nullptr) {
131 this->write(value | 0x100, 9);
132 } else {
133 this->dc_pin_->digital_write(true);
134 this->write_byte(value);
135 }
136 this->disable();
137}
138
143void ST7701S::write_sequence_(uint8_t cmd, size_t len, const uint8_t *bytes) {
144 this->write_command_(cmd);
145 while (len-- != 0)
146 this->write_data_(*bytes++);
147}
148
150 for (size_t i = 0; i != this->init_sequence_.size();) {
151 uint8_t cmd = this->init_sequence_[i++];
152 size_t len = this->init_sequence_[i++];
153 if (len == ST7701S_DELAY_FLAG) {
154 ESP_LOGV(TAG, "Delay %dms", cmd);
155 delay(cmd);
156 } else {
157 this->write_sequence_(cmd, len, &this->init_sequence_[i]);
158 i += len;
159 ESP_LOGV(TAG, "Command %X, %d bytes", cmd, len);
160 if (cmd == SW_RESET_CMD)
161 delay(6);
162 }
163 }
164 // st7701 does not appear to support axis swapping
166 this->write_command_(SDIR_CMD); // this is in the BK0 command set
167 this->write_data_(this->mirror_x_ ? 0x04 : 0x00);
168 uint8_t val = this->color_mode_ == display::COLOR_ORDER_BGR ? 0x08 : 0x00;
169 if (this->mirror_y_)
170 val |= 0x10;
172 this->write_data_(val);
173 ESP_LOGD(TAG, "write MADCTL %X", val);
175 // can't avoid this inline delay due to the need to complete setup before anything else tries to draw.
176 delay(120); // NOLINT
179 this->spi_teardown(); // SPI not needed after this
180 delay(10);
181}
182
184 ESP_LOGCONFIG("", "ST7701S RGB LCD");
185 ESP_LOGCONFIG(TAG,
186 " Height: %u\n"
187 " Width: %u",
188 this->height_, this->width_);
189 LOG_PIN(" CS Pin: ", this->cs_);
190 LOG_PIN(" DC Pin: ", this->dc_pin_);
191 LOG_PIN(" DE Pin: ", this->de_pin_);
192 LOG_PIN(" Reset Pin: ", this->reset_pin_);
193 size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]);
194 char pin_summary[GPIO_SUMMARY_MAX_LEN];
195 for (size_t i = 0; i != data_pin_count; i++) {
196 this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary));
197 ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, pin_summary);
198 }
199 ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000));
200}
201
202} // namespace esphome::st7701s
203#endif // USE_ESP32_VARIANT_ESP32S3
uint8_t h
Definition bl0906.h:2
void mark_failed()
Mark this component as failed.
virtual void digital_write(bool value)=0
int int int const uint8_t ColorOrder ColorBitness bitness
Definition display.h:392
void ESPHOME_ALWAYS_INLINE feed_wdt_per_pixel_()
Watchdog feed for per pixel loops.
Definition display.h:845
bool is_clipping() const
Definition display.h:805
int int int const uint8_t ColorOrder ColorBitness bool int int y_offset
Definition display.h:392
int int int const uint8_t ColorOrder ColorBitness bool int int int x_pad
Definition display.h:392
int int int const uint8_t * ptr
Definition display.h:391
bool ESPHOME_ALWAYS_INLINE is_point_clipped(int x, int y) const
Whether (x, y) falls outside the active clipping rectangle.
Definition display.h:810
int int int const uint8_t ColorOrder ColorBitness bool big_endian
Definition display.h:392
int int int const uint8_t ColorOrder ColorBitness bool int x_offset
Definition display.h:392
DisplayRotation rotation_
Definition display.h:863
virtual void draw_pixels_internal(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad)
Draws a block for draw_pixels_at(); the parameters are the same.
Definition display.cpp:119
size_t dump_summary(char *buffer, size_t len) const override
Definition gpio.cpp:139
uint32_t data_rate_
Definition spi.h:436
void setup() override
Definition st7701s.cpp:9
InternalGPIOPin * data_pins_[16]
Definition st7701s.h:95
void write_sequence_(uint8_t cmd, size_t len, const uint8_t *bytes)
this relies upon the init sequence being well-formed, which is guaranteed by the Python init code.
Definition st7701s.cpp:143
void write_to_display_(int x_start, int y_start, int w, int h, const uint8_t *ptr, int x_offset, int y_offset, int x_pad)
Definition st7701s.cpp:66
esp_lcd_panel_handle_t handle_
Definition st7701s.h:115
InternalGPIOPin * vsync_pin_
Definition st7701s.h:92
void draw_pixel_at(int x, int y, Color color) override
Definition st7701s.cpp:90
void draw_pixels_internal(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override
Definition st7701s.cpp:53
InternalGPIOPin * de_pin_
Definition st7701s.h:89
uint16_t vsync_pulse_width_
Definition st7701s.h:99
void write_data_(uint8_t value)
Definition st7701s.cpp:128
display::ColorOrder color_mode_
Definition st7701s.h:107
uint16_t hsync_pulse_width_
Definition st7701s.h:96
std::vector< uint8_t > init_sequence_
Definition st7701s.h:102
void dump_config() override
Definition st7701s.cpp:183
void write_command_(uint8_t value)
Definition st7701s.cpp:116
InternalGPIOPin * hsync_pin_
Definition st7701s.h:91
InternalGPIOPin * pclk_pin_
Definition st7701s.h:90
uint16_t hsync_front_porch_
Definition st7701s.h:98
void loop() override
Definition st7701s.cpp:48
mopeka_std_values val[3]
@ DISPLAY_ROTATION_0_DEGREES
Definition display.h:136
@ DISPLAY_ROTATION_270_DEGREES
Definition display.h:139
@ DISPLAY_ROTATION_180_DEGREES
Definition display.h:138
@ DISPLAY_ROTATION_90_DEGREES
Definition display.h:137
const uint8_t SLEEP_OUT
Definition st7701s.h:20
const uint8_t SDIR_CMD
Definition st7701s.h:21
const uint8_t ST7701S_DELAY_FLAG
Definition st7701s.h:28
const uint8_t INVERT_ON
Definition st7701s.h:24
const uint8_t MADCTL_CMD
Definition st7701s.h:22
const uint8_t SW_RESET_CMD
Definition st7701s.h:19
const uint8_t CMD2_BK0[5]
Definition st7701s.h:27
const uint8_t DISPLAY_ON
Definition st7701s.h:25
const uint8_t CMD2_BKSEL
Definition st7701s.h:26
const uint8_t INVERT_OFF
Definition st7701s.h:23
constexpr T convert_big_endian(T val)
Convert a value between host byte order and big endian (most significant byte first) order.
Definition helpers.h:1098
const void size_t len
Definition hal.h:68
constexpr size_t GPIO_SUMMARY_MAX_LEN
Maximum buffer size for dump_summary output.
Definition gpio_pin.h:14
void HOT delay(uint32_t ms)
Definition hal.cpp:85
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6