roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
waveshare_esp32s3_touch_lcd_43.cpp
Go to the documentation of this file.
1// 2026-02-14 19:00:00 v1.5.0 - Remove lazy init; let driver handle full reset.
2// Waveshare ESP32-S3-Touch-LCD-4.3 display device implementation.
3
5
6#if !defined(ESP32) || !(CONFIG_IDF_TARGET_ESP32S3)
7#else
8
9#include "roo_logging.h"
11
13{
14
15namespace {
16
17// CH422G I/O expander I2C addresses.
18constexpr uint8_t kCh422gAddrWrSet = 0x24;
19constexpr uint8_t kCh422gAddrWrIo = 0x38;
20constexpr uint8_t kCh422gConfigWriteEnable = 0b00000001;
21
22// CH422G pin assignments.
23constexpr uint8_t kExioTpRst = 1; // GT911 reset.
24constexpr uint8_t kExioLcdBl = 2; // LCD backlight.
25constexpr uint8_t kExioLcdRst = 3; // LCD reset.
26
27// I2C configuration.
28constexpr int kI2cSda = 8;
29constexpr int kI2cScl = 9;
30constexpr uint32_t kI2cFreq = 400000;
31
32// GT911 async reset delay. The GT911 needs ~300ms after RST release to boot.
33constexpr int kGt911AsyncInitDelayMs = 300;
34
35constexpr esp32s3_dma::Config kWaveshareConfig = {
36 .width = 800,
37 .height = 480,
38 .de = 5,
39 .hsync = 46,
40 .vsync = 3,
41 .pclk = 7,
42 .hsync_pulse_width = 4,
43 .hsync_back_porch = 8,
44 .hsync_front_porch = 8,
45 .hsync_polarity = 0,
46 .vsync_pulse_width = 4,
47 .vsync_back_porch = 16,
48 .vsync_front_porch = 16,
49 .vsync_polarity = 0,
50 .pclk_active_neg = 1,
51 .prefer_speed = 16000000,
52 .r0 = 1,
53 .r1 = 2,
54 .r2 = 42,
55 .r3 = 41,
56 .r4 = 40,
57 .g0 = 39,
58 .g1 = 0,
59 .g2 = 45,
60 .g3 = 48,
61 .g4 = 47,
62 .g5 = 21,
63 .b0 = 14,
64 .b1 = 38,
65 .b2 = 18,
66 .b3 = 17,
67 .b4 = 10,
68 .bswap = false};
69
70} // namespace
71
72WaveshareEsp32s3TouchLcd43::WaveshareEsp32s3TouchLcd43(
73 Orientation orientation, I2cMasterBusHandle i2c)
74 : i2c_(i2c),
75 ch422g_wr_set_(i2c_, kCh422gAddrWrSet),
76 ch422g_wr_io_(i2c_, kCh422gAddrWrIo),
77 display_(kWaveshareConfig),
78 // INT: inactive — board has hardware pull-down (3.6K) ensuring LOW during reset
79 // for I2C address 0x5D selection.
80 // RST: routed through CH422G expander via GpioSetter lambda.
81 touch_(i2c_,
82 GpioSetter(),
83 GpioSetter(
84 /*setter=*/[this](uint8_t state) {
85 writeEXIO(kExioTpRst, state > 0);
86 },
87 /*init=*/[this]() { writeEXIO(kExioTpRst, false); }),
88 kGt911AsyncInitDelayMs),
89 exio_shadow_(0b00001110) { // LCD_RST=1, LCD_BL=1, TP_RST=1.
90 display_.setOrientation(orientation);
91}
92
93bool WaveshareEsp32s3TouchLcd43::initTransport() {
94 if (!psramFound()) {
95 LOG(ERROR) << "PSRAM not found - required for frame buffer";
96 return false;
97 }
98
99 i2c_.init(kI2cSda, kI2cScl, kI2cFreq);
100 ch422g_wr_set_.init();
101 ch422g_wr_io_.init();
102 delay(10);
103
104 // Set initial CH422G state: LCD reset, backlight, and TP reset high.
105 exio_shadow_ = (1 << kExioLcdRst) | (1 << kExioLcdBl) | (1 << kExioTpRst);
106 writeEXIO(kExioTpRst, true);
107
108 return true;
109}
110
111DisplayDevice& WaveshareEsp32s3TouchLcd43::display() {
112 return display_;
113}
114
115TouchDevice* WaveshareEsp32s3TouchLcd43::touch() {
116 return &touch_;
117}
118
119TouchCalibration WaveshareEsp32s3TouchLcd43::touch_calibration() {
120 return TouchCalibration(0, 0, 800, 480);
121}
122
123void WaveshareEsp32s3TouchLcd43::setBacklight(bool on) {
124 writeEXIO(kExioLcdBl, on);
125}
126
127void WaveshareEsp32s3TouchLcd43::writeEXIO(uint8_t pin, bool state) {
128 if (state) {
129 exio_shadow_ |= (1 << pin);
130 } else {
131 exio_shadow_ &= ~(1 << pin);
132 }
133
134 // CH422G requires write-enable at 0x24 before data write at 0x38.
135 roo::byte enable_cmd[] = {roo::byte{kCh422gConfigWriteEnable}};
136 if (!ch422g_wr_set_.transmit(enable_cmd, 1)) {
137 LOG(ERROR) << "CH422G write enable failed";
138 return;
139 }
140
141 roo::byte output_data[] = {roo::byte{exio_shadow_}};
142 if (!ch422g_wr_io_.transmit(output_data, 1)) {
143 LOG(ERROR) << "CH422G output write failed";
144 }
145}
146
147} // namespace roo_display::products::waveshare
148
149
150#endif // ESP32 && CONFIG_IDF_TARGET_ESP32S3