ESPHome 2026.5.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 {
8namespace st7701s {
9
11 this->spi_setup();
13
14 esp_lcd_rgb_panel_config_t config{};
15 config.flags.fb_in_psram = 1;
16 config.bounce_buffer_size_px = this->width_ * 10;
17 config.num_fbs = 1;
18 config.timings.h_res = this->width_;
19 config.timings.v_res = this->height_;
20 config.timings.hsync_pulse_width = this->hsync_pulse_width_;
21 config.timings.hsync_back_porch = this->hsync_back_porch_;
22 config.timings.hsync_front_porch = this->hsync_front_porch_;
23 config.timings.vsync_pulse_width = this->vsync_pulse_width_;
24 config.timings.vsync_back_porch = this->vsync_back_porch_;
25 config.timings.vsync_front_porch = this->vsync_front_porch_;
26 config.timings.flags.pclk_active_neg = this->pclk_inverted_;
27 config.timings.pclk_hz = this->pclk_frequency_;
28 config.clk_src = LCD_CLK_SRC_PLL160M;
29 size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]);
30 for (size_t i = 0; i != data_pin_count; i++) {
31 config.data_gpio_nums[i] = static_cast<gpio_num_t>(this->data_pins_[i]->get_pin());
32 }
33 config.data_width = data_pin_count;
34 config.disp_gpio_num = GPIO_NUM_NC;
35 config.hsync_gpio_num = static_cast<gpio_num_t>(this->hsync_pin_->get_pin());
36 config.vsync_gpio_num = static_cast<gpio_num_t>(this->vsync_pin_->get_pin());
37 config.de_gpio_num = static_cast<gpio_num_t>(this->de_pin_->get_pin());
38 config.pclk_gpio_num = static_cast<gpio_num_t>(this->pclk_pin_->get_pin());
39 esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_);
40 if (err != ESP_OK) {
41 esph_log_e(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err));
42 this->mark_failed();
43 return;
44 }
45 ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_));
46 ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_));
47}
48
50 if (this->handle_ != nullptr)
51 esp_lcd_rgb_panel_restart(this->handle_);
52}
53
54void ST7701S::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
55 display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
56 if (w <= 0 || h <= 0)
57 return;
58 // if color mapping is required, pass the buck.
59 // note that endianness is not considered here - it is assumed to match!
60 if (bitness != display::COLOR_BITNESS_565) {
61 return display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset,
62 x_pad);
63 }
64 x_start += this->offset_x_;
65 y_start += this->offset_y_;
66 esp_err_t err;
67 // x_ and y_offset are offsets into the source buffer, unrelated to our own offsets into the display.
68 if (x_offset == 0 && x_pad == 0 && y_offset == 0) {
69 // 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
70 err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y_start, x_start + w, y_start + h, ptr);
71 } else {
72 // draw line by line
73 auto stride = x_offset + w + x_pad;
74 for (int y = 0; y != h; y++) {
75 err = esp_lcd_panel_draw_bitmap(this->handle_, x_start, y + y_start, x_start + w, y + y_start + 1,
76 ptr + ((y + y_offset) * stride + x_offset) * 2);
77 if (err != ESP_OK)
78 break;
79 }
80 }
81 if (err != ESP_OK)
82 esph_log_e(TAG, "lcd_lcd_panel_draw_bitmap failed: %s", esp_err_to_name(err));
83}
84
85void ST7701S::draw_pixel_at(int x, int y, Color color) {
86 if (!this->get_clipping().inside(x, y))
87 return; // NOLINT
88
89 switch (this->rotation_) {
91 break;
93 std::swap(x, y);
94 x = this->width_ - x - 1;
95 break;
97 x = this->width_ - x - 1;
98 y = this->height_ - y - 1;
99 break;
101 std::swap(x, y);
102 y = this->height_ - y - 1;
103 break;
104 }
106
107 this->draw_pixels_at(x, y, 1, 1, (const uint8_t *) &pixel, display::COLOR_ORDER_RGB, display::COLOR_BITNESS_565, true,
108 0, 0, 0);
109 App.feed_wdt();
110}
111
112void ST7701S::write_command_(uint8_t value) {
113 this->enable();
114 if (this->dc_pin_ == nullptr) {
115 this->write(value, 9);
116 } else {
117 this->dc_pin_->digital_write(false);
118 this->write_byte(value);
119 this->dc_pin_->digital_write(true);
120 }
121 this->disable();
122}
123
124void ST7701S::write_data_(uint8_t value) {
125 this->enable();
126 if (this->dc_pin_ == nullptr) {
127 this->write(value | 0x100, 9);
128 } else {
129 this->dc_pin_->digital_write(true);
130 this->write_byte(value);
131 }
132 this->disable();
133}
134
139void ST7701S::write_sequence_(uint8_t cmd, size_t len, const uint8_t *bytes) {
140 this->write_command_(cmd);
141 while (len-- != 0)
142 this->write_data_(*bytes++);
143}
144
146 for (size_t i = 0; i != this->init_sequence_.size();) {
147 uint8_t cmd = this->init_sequence_[i++];
148 size_t len = this->init_sequence_[i++];
149 if (len == ST7701S_DELAY_FLAG) {
150 ESP_LOGV(TAG, "Delay %dms", cmd);
151 delay(cmd);
152 } else {
153 this->write_sequence_(cmd, len, &this->init_sequence_[i]);
154 i += len;
155 ESP_LOGV(TAG, "Command %X, %d bytes", cmd, len);
156 if (cmd == SW_RESET_CMD)
157 delay(6);
158 }
159 }
160 // st7701 does not appear to support axis swapping
162 this->write_command_(SDIR_CMD); // this is in the BK0 command set
163 this->write_data_(this->mirror_x_ ? 0x04 : 0x00);
164 uint8_t val = this->color_mode_ == display::COLOR_ORDER_BGR ? 0x08 : 0x00;
165 if (this->mirror_y_)
166 val |= 0x10;
168 this->write_data_(val);
169 ESP_LOGD(TAG, "write MADCTL %X", val);
171 // can't avoid this inline delay due to the need to complete setup before anything else tries to draw.
172 delay(120); // NOLINT
175 this->spi_teardown(); // SPI not needed after this
176 delay(10);
177}
178
180 ESP_LOGCONFIG("", "ST7701S RGB LCD");
181 ESP_LOGCONFIG(TAG,
182 " Height: %u\n"
183 " Width: %u",
184 this->height_, this->width_);
185 LOG_PIN(" CS Pin: ", this->cs_);
186 LOG_PIN(" DC Pin: ", this->dc_pin_);
187 LOG_PIN(" DE Pin: ", this->de_pin_);
188 LOG_PIN(" Reset Pin: ", this->reset_pin_);
189 size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]);
190 char pin_summary[GPIO_SUMMARY_MAX_LEN];
191 for (size_t i = 0; i != data_pin_count; i++) {
192 this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary));
193 ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, pin_summary);
194 }
195 ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000));
196}
197
198} // namespace st7701s
199} // namespace esphome
200#endif // USE_ESP32_VARIANT_ESP32S3
uint8_t h
Definition bl0906.h:2
void feed_wdt()
Feed the task watchdog.
void mark_failed()
Mark this component as failed.
virtual void digital_write(bool value)=0
virtual size_t dump_summary(char *buffer, size_t len) const
Write a summary of this pin to the provided buffer.
Definition gpio.h:129
virtual uint8_t get_pin() const =0
static uint16_t color_to_565(Color color, ColorOrder color_order=ColorOrder::COLOR_ORDER_RGB)
Rect get_clipping() const
Get the current the clipping rectangle.
Definition display.cpp:766
DisplayRotation rotation_
Definition display.h:790
virtual void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order, ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad)
Given an array of pixels encoded in the nominated format, draw these into the display's buffer.
Definition display.cpp:54
uint32_t data_rate_
Definition spi.h:412
void setup() override
Definition st7701s.cpp:10
InternalGPIOPin * data_pins_[16]
Definition st7701s.h:93
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override
Definition st7701s.cpp:54
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:139
uint16_t vsync_front_porch_
Definition st7701s.h:99
esp_lcd_panel_handle_t handle_
Definition st7701s.h:113
InternalGPIOPin * vsync_pin_
Definition st7701s.h:90
void draw_pixel_at(int x, int y, Color color) override
Definition st7701s.cpp:85
InternalGPIOPin * de_pin_
Definition st7701s.h:87
uint16_t vsync_pulse_width_
Definition st7701s.h:97
void write_data_(uint8_t value)
Definition st7701s.cpp:124
display::ColorOrder color_mode_
Definition st7701s.h:105
uint16_t hsync_pulse_width_
Definition st7701s.h:94
std::vector< uint8_t > init_sequence_
Definition st7701s.h:100
void dump_config() override
Definition st7701s.cpp:179
void write_command_(uint8_t value)
Definition st7701s.cpp:112
InternalGPIOPin * hsync_pin_
Definition st7701s.h:89
InternalGPIOPin * pclk_pin_
Definition st7701s.h:88
uint16_t hsync_front_porch_
Definition st7701s.h:96
void loop() override
Definition st7701s.cpp:49
mopeka_std_values val[3]
@ DISPLAY_ROTATION_0_DEGREES
Definition display.h:135
@ DISPLAY_ROTATION_270_DEGREES
Definition display.h:138
@ DISPLAY_ROTATION_180_DEGREES
Definition display.h:137
@ DISPLAY_ROTATION_90_DEGREES
Definition display.h:136
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
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
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:937
std::string size_t len
Definition helpers.h:1045
constexpr size_t GPIO_SUMMARY_MAX_LEN
Maximum buffer size for dump_summary output.
Definition gpio.h:13
void HOT delay(uint32_t ms)
Definition core.cpp:28
Application App
Global storage of Application pointer - only one Application can exist.
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6