From 1cdd5c3f0848a845c689bb17382c64d4cc799f22 Mon Sep 17 00:00:00 2001 From: gemu Date: Sun, 18 Dec 2022 14:06:04 +0100 Subject: [PATCH] Udisplay support for rgb displays (#17414) * add gt911 * add rgb display mode * add gt911 * add gt911 * add gt911 * add sunton descriptor * fix divide by zero crash with sunton --- lib/lib_display/GT911/GT911.cpp | 290 ++++++++++++++ lib/lib_display/GT911/GT911.h | 179 +++++++++ lib/lib_display/UDisplay/uDisplay.cpp | 362 +++++++++++++++++- lib/lib_display/UDisplay/uDisplay.h | 63 ++- tasmota/displaydesc/ST7262_rgb16_display.ini | 5 + tasmota/tasmota_support/support_esp.ino | 5 +- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 49 ++- .../xdsp_17_universal.ino | 69 +++- 9 files changed, 985 insertions(+), 39 deletions(-) create mode 100755 lib/lib_display/GT911/GT911.cpp create mode 100755 lib/lib_display/GT911/GT911.h create mode 100644 tasmota/displaydesc/ST7262_rgb16_display.ini diff --git a/lib/lib_display/GT911/GT911.cpp b/lib/lib_display/GT911/GT911.cpp new file mode 100755 index 000000000..37dbd72c0 --- /dev/null +++ b/lib/lib_display/GT911/GT911.cpp @@ -0,0 +1,290 @@ +#include +#include +#include "GT911.h" + +#undef log_d +#define log_d +#undef log_e +#define log_e + +#ifdef ESP8266 +#define ESP_OK 0 +#define ESP_FAIL -1 +#endif + +//#define log_d Serial.printf + +GT911::GT911() {} + +volatile uint8_t gt911_irq_trigger = 0; +void ICACHE_RAM_ATTR ___GT911IRQ___() +{ + noInterrupts(); + gt911_irq_trigger = 1; + interrupts(); +} + +int32_t GT911::begin(TwoWire *use_wire, int8_t pin_int, int8_t pin_res, uint16_t xs, uint16_t ys) +{ + log_d("GT911: Initialization"); + + if (pin_int >= 0) { + pinMode(pin_int, INPUT); // Startup sequence PIN part + } + if (pin_res >= 0) { + pinMode(pin_res, OUTPUT); // Startup sequence PIN part + digitalWrite(pin_res, 0); + delay(1); + digitalWrite(pin_res, 1); + } + delay(100); + wire = use_wire; + + wire->beginTransmission(0x14); + if (wire->endTransmission()) + { + wire->beginTransmission(0x5D); + if (wire->endTransmission()) + { + log_e("Touch screen IIC connection error"); + return ESP_FAIL; + } + _iic_addr = 0x5D; + } + + if (pin_int >= 0) { + attachInterrupt(pin_int, ___GT911IRQ___, FALLING); + } + + readBlockData(configBuf, GT911_CONFIG_START, GT911_CONFIG_SIZE); + + uint16_t curx = configBuf[GT911_X_OUTPUT_MAX_LOW - GT911_CONFIG_START] | (configBuf[GT911_X_OUTPUT_MAX_HIGH - GT911_CONFIG_START] << 8); + uint16_t cury = configBuf[GT911_Y_OUTPUT_MAX_LOW - GT911_CONFIG_START] | (configBuf[GT911_Y_OUTPUT_MAX_HIGH - GT911_CONFIG_START] << 8); + + if (curx != xs || cury != ys) { + setResolution(xs, ys); + } + + log_d("GT911: initialized"); + + return ESP_OK; +} + + +void GT911::write(uint16_t addr, uint8_t data) +{ + wire->beginTransmission(_iic_addr); + wire->write((uint8_t)(addr >> 8)); + wire->write((uint8_t)addr); + wire->write(data); + wire->endTransmission(true); +} + +void GT911::write(uint16_t addr, const uint8_t *data, uint16_t len) +{ + wire->beginTransmission(_iic_addr); + wire->write((uint8_t)(addr >> 8)); + wire->write((uint8_t)addr); + wire->write(data, len); + wire->endTransmission(true); +} + +uint8_t GT911::read(uint16_t addr) +{ + wire->flush(); + wire->beginTransmission(_iic_addr); + wire->write((uint8_t)(addr >> 8)); + wire->write((uint8_t)addr); + wire->endTransmission(false); + wire->requestFrom((uint8_t)_iic_addr, (uint8_t)1); + return wire->read(); +} + +void GT911::read(uint16_t addr, uint8_t *buf, uint16_t len) +{ + wire->flush(); + wire->beginTransmission(_iic_addr); + wire->write((uint8_t)(addr >> 8)); + wire->write((uint8_t)addr); + wire->endTransmission(false); + wire->requestFrom((int)_iic_addr, (int)len); + wire->readBytes(buf, len); +} + +void GT911::readBlockData(uint8_t *buf, uint16_t reg, uint8_t size) { + wire->beginTransmission(_iic_addr); + wire->write(highByte(reg)); + wire->write(lowByte(reg)); + wire->endTransmission(); + wire->requestFrom(_iic_addr, size); + for (uint8_t i = 0; i < size; i++) { + buf[i] = wire->read(); + } +} + + +void GT911::calculateChecksum() { + uint8_t checksum = 0; + for (uint8_t i = 0; i < GT911_CONFIG_SIZE - 1 ; i++) { + checksum += configBuf[i]; + } + checksum = (~checksum) + 1; + configBuf[GT911_CONFIG_CHKSUM - GT911_CONFIG_START] = checksum; +} + +void GT911::reflashConfig() { + calculateChecksum(); + write(GT911_X_OUTPUT_MAX_LOW, configBuf[GT911_X_OUTPUT_MAX_LOW - GT911_CONFIG_START]); + write(GT911_X_OUTPUT_MAX_HIGH, configBuf[GT911_X_OUTPUT_MAX_HIGH - GT911_CONFIG_START]); + write(GT911_Y_OUTPUT_MAX_LOW, configBuf[GT911_Y_OUTPUT_MAX_LOW - GT911_CONFIG_START]); + write(GT911_Y_OUTPUT_MAX_HIGH, configBuf[GT911_Y_OUTPUT_MAX_HIGH - GT911_CONFIG_START]); + write(GT911_CONFIG_CHKSUM, configBuf[GT911_CONFIG_CHKSUM - GT911_CONFIG_START]); + write(GT911_CONFIG_FRESH, 1); +} + +void GT911::setResolution(uint16_t _width, uint16_t _height) { + configBuf[GT911_X_OUTPUT_MAX_LOW - GT911_CONFIG_START] = lowByte(_width); + configBuf[GT911_X_OUTPUT_MAX_HIGH - GT911_CONFIG_START] = highByte(_width); + configBuf[GT911_Y_OUTPUT_MAX_LOW - GT911_CONFIG_START] = lowByte(_height); + configBuf[GT911_Y_OUTPUT_MAX_HIGH - GT911_CONFIG_START] = highByte(_height); + reflashConfig(); +} + +bool GT911::avaliable() +{ + if(gt911_irq_trigger == 1) + { + gt911_irq_trigger = 0; + return true; + } + return false; +} + +void GT911::flush(void) +{ + write(0x814E, 0x00); + gt911_irq_trigger = 0; + _num = 0; + _is_finger_up = 0; +} + +void GT911::update() +{ + uint8_t r814e = read(0x814E); + uint8_t num = r814e & 0x0F; + if(r814e & 0x80) + { + if(num != 0) + { + _is_finger_up = false; + _num = num; + uint8_t data[num * 8]; + read(0x8150, data, num * 8); + for(int j = 0; j < num; j++) + { + uint8_t *buf = data + j * 8; + + if(_rotate == ROTATE_0) + { + _fingers[j].x = (buf[3] << 8) | buf[2]; + _fingers[j].y = 540 - ((buf[1] << 8) | buf[0]); + } + else if(_rotate == ROTATE_180) + { + _fingers[j].x = 960 - ((buf[3] << 8) | buf[2]); + _fingers[j].y = (buf[1] << 8) | buf[0]; + } + else if(_rotate == ROTATE_270) + { + _fingers[j].x = 540 - ((buf[1] << 8) | buf[0]); + _fingers[j].y = 960 - ((buf[3] << 8) | buf[2]); + } + else + { + _fingers[j].x = (buf[1] << 8) | buf[0]; + _fingers[j].y = (buf[3] << 8) | buf[2]; + } + + _fingers[j].size = (buf[5] << 8) | buf[4]; + _fingers[j].id = buf[7]; + } + } + else + { + _is_finger_up = true; + } + write(0x814E, 0x00); + } + else + { + _is_finger_up = 1; + } +} + +bool GT911::isFingerUp(void) +{ + if(_is_finger_up == 1) + { + _is_finger_up = 0; + return true; + } + return false; +} + +void GT911::SetRotation(uint16_t rotate) +{ + if(rotate < 4) + { + this->_rotate = rotate; + } + else if(rotate < 90) + { + this->_rotate = ROTATE_0; + } + else if(rotate < 180) + { + this->_rotate = ROTATE_90; + } + else if(rotate < 270) + { + this->_rotate = ROTATE_180; + } + else + { + this->_rotate = ROTATE_270; + } +} + +tp_finger_t GT911::readFinger(uint8_t num) +{ + if(num > 2) + { + num = 1; + } + return this->_fingers[num]; +} + +uint16_t GT911::readFingerID(uint8_t num) +{ + return this->_fingers[num].id; +} + +uint16_t GT911::readFingerSize(uint8_t num) +{ + return this->_fingers[num].size; +} + +uint16_t GT911::readFingerX(uint8_t num) +{ + return this->_fingers[num].x; +} + +uint16_t GT911::readFingerY(uint8_t num) +{ + return this->_fingers[num].y; +} + +uint8_t GT911::getFingerNum(void) +{ + return _num; +} diff --git a/lib/lib_display/GT911/GT911.h b/lib/lib_display/GT911/GT911.h new file mode 100755 index 000000000..65da24cd7 --- /dev/null +++ b/lib/lib_display/GT911/GT911.h @@ -0,0 +1,179 @@ +#ifndef GT911_H +#define GT911_H + +#include +#include + + +// Real-time command (Write only) +#define GT911_COMMAND (uint16_t)0x8040 +#define GT911_ESD_CHECK (uint16_t)0x8041 +#define GT911_COMMAND_CHECK (uint16_t)0x8046 + +// Configuration information (R/W) +#define GT911_CONFIG_START (uint16_t)0x8047 +#define GT911_CONFIG_VERSION (uint16_t)0x8047 +#define GT911_X_OUTPUT_MAX_LOW (uint16_t)0x8048 +#define GT911_X_OUTPUT_MAX_HIGH (uint16_t)0x8049 +#define GT911_Y_OUTPUT_MAX_LOW (uint16_t)0x804A +#define GT911_Y_OUTPUT_MAX_HIGH (uint16_t)0x804B +#define GT911_TOUCH_NUMBER (uint16_t)0x804C +#define GT911_MODULE_SWITCH_1 (uint16_t)0x804D +#define GT911_MODULE_SWITCH_2 (uint16_t)0x804E +#define GT911_SHAKE_COUNT (uint16_t)0x804F +#define GT911_FILTER (uint16_t)0x8050 +#define GT911_LARGE_TOUCH (uint16_t)0x8051 +#define GT911_NOISE_REDUCTION (uint16_t)0x8052 +#define GT911_SCREEN_TOUCH_LEVEL (uint16_t)0x8053 +#define GT911_SCREEN_RELEASE_LEVEL (uint16_t)0x8054 +#define GT911_LOW_POWER_CONTROL (uint16_t)0x8055 +#define GT911_REFRESH_RATE (uint16_t)0x8056 +#define GT911_X_THRESHOLD (uint16_t)0x8057 +#define GT911_Y_THRESHOLD (uint16_t)0x8058 +#define GT911_X_SPEED_LIMIT (uint16_t)0x8059 //Reserve +#define GT911_Y_SPEED_LIMIT (uint16_t)0x805A //Reserve +#define GT911_SPACE_TOP_BOTTOM (uint16_t)0x805B +#define GT911_SPACE_LEFT_RIGHT (uint16_t)0x805C +#define GT911_MINI_FILTER (uint16_t)0x805D +#define GT911_STRETCH_R0 (uint16_t)0x805E +#define GT911_STRETCH_R1 (uint16_t)0x805F +#define GT911_STRETCH_R2 (uint16_t)0x8060 +#define GT911_STRETCH_RM (uint16_t)0x8061 +#define GT911_DRV_GROUPA_NUM (uint16_t)0x8062 +#define GT911_DRV_GROUPB_NUM (uint16_t)0x8063 +#define GT911_SENSOR_NUM (uint16_t)0x8064 +#define GT911_FREQ_A_FACTOR (uint16_t)0x8065 +#define GT911_FREQ_B_FACTOR (uint16_t)0x8066 +#define GT911_PANEL_BIT_FREQ_L (uint16_t)0x8067 +#define GT911_PANEL_BIT_FREQ_H (uint16_t)0x8068 +#define GT911_PANEL_SENSOR_TIME_L (uint16_t)0x8069 //Reserve +#define GT911_PANEL_SENSOR_TIME_H (uint16_t)0x806A +#define GT911_PANEL_TX_GAIN (uint16_t)0x806B +#define GT911_PANEL_RX_GAIN (uint16_t)0x806C +#define GT911_PANEL_DUMP_SHIFT (uint16_t)0x806D +#define GT911_DRV_FRAME_CONTROL (uint16_t)0x806E +#define GT911_CHARGING_LEVEL_UP (uint16_t)0x806F +#define GT911_MODULE_SWITCH3 (uint16_t)0x8070 +#define GT911_GESTURE_DIS (uint16_t)0X8071 +#define GT911_GESTURE_LONG_PRESS_TIME (uint16_t)0x8072 +#define GT911_X_Y_SLOPE_ADJUST (uint16_t)0X8073 +#define GT911_GESTURE_CONTROL (uint16_t)0X8074 +#define GT911_GESTURE_SWITCH1 (uint16_t)0X8075 +#define GT911_GESTURE_SWITCH2 (uint16_t)0X8076 +#define GT911_GESTURE_REFRESH_RATE (uint16_t)0x8077 +#define GT911_GESTURE_TOUCH_LEVEL (uint16_t)0x8078 +#define GT911_NEWGREENWAKEUPLEVEL (uint16_t)0x8079 +#define GT911_FREQ_HOPPING_START (uint16_t)0x807A +#define GT911_FREQ_HOPPING_END (uint16_t)0X807B +#define GT911_NOISE_DETECT_TIMES (uint16_t)0x807C +#define GT911_HOPPING_FLAG (uint16_t)0X807D +#define GT911_HOPPING_THRESHOLD (uint16_t)0X807E +#define GT911_NOISE_THRESHOLD (uint16_t)0X807F //Reserve +#define GT911_NOISE_MIN_THRESHOLD (uint16_t)0X8080 +#define GT911_HOPPING_SENSOR_GROUP (uint16_t)0X8082 +#define GT911_HOPPING_SEG1_NORMALIZE (uint16_t)0X8083 +#define GT911_HOPPING_SEG1_FACTOR (uint16_t)0X8084 +#define GT911_MAIN_CLOCK_AJDUST (uint16_t)0X8085 +#define GT911_HOPPING_SEG2_NORMALIZE (uint16_t)0X8086 +#define GT911_HOPPING_SEG2_FACTOR (uint16_t)0X8087 +#define GT911_HOPPING_SEG3_NORMALIZE (uint16_t)0X8089 +#define GT911_HOPPING_SEG3_FACTOR (uint16_t)0X808A +#define GT911_HOPPING_SEG4_NORMALIZE (uint16_t)0X808C +#define GT911_HOPPING_SEG4_FACTOR (uint16_t)0X808D +#define GT911_HOPPING_SEG5_NORMALIZE (uint16_t)0X808F +#define GT911_HOPPING_SEG5_FACTOR (uint16_t)0X8090 +#define GT911_HOPPING_SEG6_NORMALIZE (uint16_t)0X8092 +#define GT911_KEY_1 (uint16_t)0X8093 +#define GT911_KEY_2 (uint16_t)0X8094 +#define GT911_KEY_3 (uint16_t)0X8095 +#define GT911_KEY_4 (uint16_t)0X8096 +#define GT911_KEY_AREA (uint16_t)0X8097 +#define GT911_KEY_TOUCH_LEVEL (uint16_t)0X8098 +#define GT911_KEY_LEAVE_LEVEL (uint16_t)0X8099 +#define GT911_KEY_SENS_1_2 (uint16_t)0X809A +#define GT911_KEY_SENS_3_4 (uint16_t)0X809B +#define GT911_KEY_RESTRAIN (uint16_t)0X809C +#define GT911_KEY_RESTRAIN_TIME (uint16_t)0X809D +#define GT911_GESTURE_LARGE_TOUCH (uint16_t)0X809E +#define GT911_HOTKNOT_NOISE_MAP (uint16_t)0X80A1 +#define GT911_LINK_THRESHOLD (uint16_t)0X80A2 +#define GT911_PXY_THRESHOLD (uint16_t)0X80A3 +#define GT911_GHOT_DUMP_SHIFT (uint16_t)0X80A4 +#define GT911_GHOT_RX_GAIN (uint16_t)0X80A5 +#define GT911_FREQ_GAIN0 (uint16_t)0X80A6 +#define GT911_FREQ_GAIN1 (uint16_t)0X80A7 +#define GT911_FREQ_GAIN2 (uint16_t)0X80A8 +#define GT911_FREQ_GAIN3 (uint16_t)0X80A9 +#define GT911_COMBINE_DIS (uint16_t)0X80B3 +#define GT911_SPLIT_SET (uint16_t)0X80B4 +#define GT911_SENSOR_CH0 (uint16_t)0X80B7 +#define GT911_DRIVER_CH0 (uint16_t)0X80D5 +#define GT911_CONFIG_CHKSUM (uint16_t)0X80FF +#define GT911_CONFIG_FRESH (uint16_t)0X8100 +#define GT911_CONFIG_SIZE (uint16_t)0xFF-0x46 +// Coordinate information +#define GT911_PRODUCT_ID (uint16_t)0X8140 +#define GT911_FIRMWARE_VERSION (uint16_t)0X8140 +#define GT911_RESOLUTION (uint16_t)0X8140 +#define GT911_VENDOR_ID (uint16_t)0X8140 +#define GT911_IMFORMATION (uint16_t)0X8140 +#define GT911_POINT_INFO (uint16_t)0X814E +#define GT911_POINT_1 (uint16_t)0X814F +#define GT911_POINT_2 (uint16_t)0X8157 +#define GT911_POINT_3 (uint16_t)0X815F +#define GT911_POINT_4 (uint16_t)0X8167 +#define GT911_POINT_5 (uint16_t)0X816F +#define GT911_POINTS_REG {GT911_POINT_1, GT911_POINT_2, GT911_POINT_3, GT911_POINT_4, GT911_POINT_5} + +typedef struct +{ + uint16_t x; + uint16_t y; + uint16_t id; + uint16_t size; +}tp_finger_t; + +class GT911 +{ +public: + static const uint8_t ROTATE_0 = 0; + static const uint8_t ROTATE_90 = 1; + static const uint8_t ROTATE_180 = 2; + static const uint8_t ROTATE_270 = 3; + +public: + GT911(); + int32_t begin(TwoWire *use_wire, int8_t pin_int, int8_t pin_res, uint16_t xs, uint16_t ys); + bool avaliable(); + void update(); + void SetRotation(uint16_t rotate); + tp_finger_t readFinger(uint8_t num); + uint16_t readFingerX(uint8_t num); + uint16_t readFingerY(uint8_t num); + uint16_t readFingerID(uint8_t num); + uint16_t readFingerSize(uint8_t num); + uint8_t getFingerNum(void); + bool isFingerUp(void); + void flush(void); + +private: + void write(uint16_t addr, uint8_t data); + void write(uint16_t addr, const uint8_t *data, uint16_t len); + uint8_t read(uint16_t addr); + void read(uint16_t addr, uint8_t *buf, uint16_t len); + uint8_t calcChecksum(const uint8_t *buf, uint8_t len); + void reflashConfig(); + void calculateChecksum(); + void setResolution(uint16_t _width, uint16_t _height); + void readBlockData(uint8_t *buf, uint16_t reg, uint8_t size); + + bool _is_finger_up = false; + uint8_t _num = 0; + uint8_t _rotate = ROTATE_90; + tp_finger_t _fingers[2]; + uint8_t _iic_addr = 0x14; + TwoWire *wire; + uint8_t configBuf[GT911_CONFIG_SIZE]; +}; + +#endif diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index d3b55316e..d9e2b5310 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -24,8 +24,14 @@ #include "esp8266toEsp32.h" #endif + +extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size); + + //#define UDSP_DEBUG +#define renderer_swap(a, b) { int16_t t = a; a = b; b = t; } + const uint16_t udisp_colors[]={UDISP_BLACK,UDISP_WHITE,UDISP_RED,UDISP_GREEN,UDISP_BLUE,UDISP_CYAN,UDISP_MAGENTA,\ UDISP_YELLOW,UDISP_NAVY,UDISP_DARKGREEN,UDISP_DARKCYAN,UDISP_MAROON,UDISP_PURPLE,UDISP_OLIVE,\ UDISP_LIGHTGREY,UDISP_DARKGREY,UDISP_ORANGE,UDISP_GREENYELLOW,UDISP_PINK}; @@ -93,6 +99,10 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { lut_num = 0; lvgl_param.data = 0; lvgl_param.fluslines = 40; + rot_t[0] = 0; + rot_t[1] = 1; + rot_t[2] = 2; + rot_t[3] = 3; for (uint32_t cnt = 0; cnt < 5; cnt++) { lut_cnt[cnt] = 0; @@ -199,6 +209,26 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { } } spi_speed = next_val(&lp1); +#endif // USE_ESP32_S3 + section = 0; + } else if (!strncmp(ibuff, "RGB", 3)) { +#ifdef USE_ESP32_S3 + interface = _UDSP_RGB; + + de = next_val(&lp1); + vsync = next_val(&lp1); + hsync = next_val(&lp1); + pclk = next_val(&lp1); + bpanel = next_val(&lp1); + + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + par_dbl[cnt] = next_val(&lp1); + } + + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + par_dbh[cnt] = next_val(&lp1); + } + spi_speed = next_val(&lp1); #endif // USE_ESP32_S3 section = 0; } @@ -236,9 +266,23 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { } } break; +#ifdef USE_ESP32_S3 + case 'V': + hsync_polarity = next_val(&lp1); + hsync_front_porch = next_val(&lp1); + hsync_pulse_width = next_val(&lp1); + hsync_back_porch = next_val(&lp1); + vsync_polarity = next_val(&lp1); + vsync_front_porch = next_val(&lp1); + vsync_pulse_width = next_val(&lp1); + vsync_back_porch = next_val(&lp1); + pclk_active_neg = next_val(&lp1); + break; +#endif // USE_ESP32_S3 case 'o': dsp_off = next_hex(&lp1); break; + case 'O': dsp_on = next_hex(&lp1); break; @@ -247,27 +291,35 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { startline = next_hex(&lp1); break; case '0': - rot[0] = next_hex(&lp1); - x_addr_offs[0] = next_hex(&lp1); - y_addr_offs[0] = next_hex(&lp1); + if (interface != _UDSP_RGB) { + rot[0] = next_hex(&lp1); + x_addr_offs[0] = next_hex(&lp1); + y_addr_offs[0] = next_hex(&lp1); + } rot_t[0] = next_hex(&lp1); break; case '1': - rot[1] = next_hex(&lp1); - x_addr_offs[1] = next_hex(&lp1); - y_addr_offs[1] = next_hex(&lp1); + if (interface != _UDSP_RGB) { + rot[1] = next_hex(&lp1); + x_addr_offs[1] = next_hex(&lp1); + y_addr_offs[1] = next_hex(&lp1); + } rot_t[1] = next_hex(&lp1); break; case '2': - rot[2] = next_hex(&lp1); - x_addr_offs[2] = next_hex(&lp1); - y_addr_offs[2] = next_hex(&lp1); + if (interface != _UDSP_RGB) { + rot[2] = next_hex(&lp1); + x_addr_offs[2] = next_hex(&lp1); + y_addr_offs[2] = next_hex(&lp1); + } rot_t[2] = next_hex(&lp1); break; case '3': - rot[3] = next_hex(&lp1); - x_addr_offs[3] = next_hex(&lp1); - y_addr_offs[3] = next_hex(&lp1); + if (interface != _UDSP_RGB) { + rot[3] = next_hex(&lp1); + x_addr_offs[3] = next_hex(&lp1); + y_addr_offs[3] = next_hex(&lp1); + } rot_t[3] = next_hex(&lp1); break; case 'A': @@ -449,9 +501,39 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { #endif // USE_ESP32_S3 } -#endif -} + if (interface == _UDSP_RGB) { +#ifdef USE_ESP32_S3 + Serial.printf("rgb de: %d\n", de); + Serial.printf("rgb vsync: %d\n", vsync); + Serial.printf("rgb hsync : %d\n", hsync); + Serial.printf("rgb pclk : %d\n", pclk); + Serial.printf("rgb bp : %d\n", bpanel); + + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + Serial.printf("rgb d%d: %d\n", cnt, par_dbl[cnt]); + } + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + Serial.printf("rgb d%d: %d\n", cnt + 8, par_dbh[cnt]); + } + + Serial.printf("rgb freq : %d\n", spi_speed); + + Serial.printf("rgb hsync_polarity: %d\n", hsync_polarity); + Serial.printf("rgb hsync_front_porch: %d\n", hsync_front_porch); + Serial.printf("rgb hsync_pulse_width : %d\n", hsync_pulse_width); + Serial.printf("rgb hsync_back_porch : %d\n", hsync_back_porch); + Serial.printf("rgb vsync_polarity : %d\n", vsync_polarity); + Serial.printf("rgb vsync_front_porch : %d\n", vsync_front_porch); + Serial.printf("rgb vsync_pulse_width : %d\n", vsync_pulse_width); + Serial.printf("rgb vsync_back_porch : %d\n", vsync_back_porch); + Serial.printf("rgb pclk_active_neg : %d\n", pclk_active_neg); + +#endif // USE_ESP32_S3 + } +#endif + +} Renderer *uDisplay::Init(void) { extern bool UsePSRAM(void); @@ -553,7 +635,6 @@ Renderer *uDisplay::Init(void) { spiSettings = SPISettings((uint32_t)spi_speed*1000000, MSBFIRST, SPI_MODE3); SPI_BEGIN_TRANSACTION - if (reset >= 0) { pinMode(reset, OUTPUT); digitalWrite(reset, HIGH); @@ -612,6 +693,69 @@ Renderer *uDisplay::Init(void) { } + if (interface == _UDSP_RGB) { +#ifdef USE_ESP32_S3 + + if (bpanel >= 0) { + analogWrite(bpanel, 32); + } + esp_lcd_rgb_panel_config_t *_panel_config = (esp_lcd_rgb_panel_config_t *)heap_caps_calloc(1, sizeof(esp_lcd_rgb_panel_config_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + + _panel_config->clk_src = LCD_CLK_SRC_PLL160M; + + if (spi_speed > 14) { + spi_speed = 14; + } + _panel_config->timings.pclk_hz = spi_speed*1000000; + _panel_config->timings.h_res = gxs; + _panel_config->timings.v_res = gys; + + _panel_config->timings.hsync_pulse_width = hsync_pulse_width; + _panel_config->timings.hsync_back_porch = hsync_back_porch; + _panel_config->timings.hsync_front_porch = hsync_front_porch; + _panel_config->timings.vsync_pulse_width = vsync_pulse_width; + _panel_config->timings.vsync_back_porch = vsync_back_porch; + _panel_config->timings.vsync_front_porch = vsync_front_porch; + _panel_config->timings.flags.hsync_idle_low = (hsync_polarity == 0) ? 1 : 0; + _panel_config->timings.flags.vsync_idle_low = (vsync_polarity == 0) ? 1 : 0; + _panel_config->timings.flags.de_idle_high = 0; + _panel_config->timings.flags.pclk_active_neg = pclk_active_neg; + _panel_config->timings.flags.pclk_idle_high = 0; + + _panel_config->data_width = 16; // RGB565 in parallel mode, thus 16bit in width + _panel_config->sram_trans_align = 8; + _panel_config->psram_trans_align = 64; + _panel_config->hsync_gpio_num = hsync; + _panel_config->vsync_gpio_num = vsync; + _panel_config->de_gpio_num = de; + _panel_config->pclk_gpio_num = pclk; + + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + _panel_config->data_gpio_nums[cnt] = par_dbh[cnt]; + } + for (uint32_t cnt = 0; cnt < 8; cnt ++) { + _panel_config->data_gpio_nums[cnt + 8] = par_dbl[cnt]; + } + _panel_config->disp_gpio_num = GPIO_NUM_NC; + + _panel_config->flags.disp_active_low = 0; + _panel_config->flags.relax_on_idle = 0; + _panel_config->flags.fb_in_psram = 1; // allocate frame buffer in PSRAM + + ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(_panel_config, &_panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_reset(_panel_handle)); + ESP_ERROR_CHECK(esp_lcd_panel_init(_panel_handle)); + + uint16_t color = random(0xffff); + ESP_ERROR_CHECK(_panel_handle->draw_bitmap(_panel_handle, 0, 0, 1, 1, &color)); + + _rgb_panel = __containerof(_panel_handle, esp_rgb_panel_t, base); + + rgb_fb = (uint16_t *)_rgb_panel->fb; + +#endif // USE_ESP32_S3 + } + if (interface == _UDSP_PAR8 || interface == _UDSP_PAR16) { #ifdef USE_ESP32_S3 @@ -760,10 +904,14 @@ Renderer *uDisplay::Init(void) { if (ep_mode == 1) Init_EPD(DISPLAY_INIT_PARTIAL); } +#ifdef UDSP_DEBUG + Serial.printf("Dsp Init 1 complete \n"); +#endif return this; } + void uDisplay::DisplayInit(int8_t p, int8_t size, int8_t rot, int8_t font) { if (p != DISPLAY_INIT_MODE && ep_mode) { if (p == DISPLAY_INIT_PARTIAL) { @@ -800,7 +948,7 @@ void uDisplay::DisplayInit(int8_t p, int8_t size, int8_t rot, int8_t font) { } #ifdef UDSP_DEBUG - Serial.printf("Dsp Init complete \n"); + Serial.printf("Dsp Init 2 complete \n"); #endif } } @@ -960,6 +1108,10 @@ void uDisplay::i2c_command(uint8_t val) { void uDisplay::Updateframe(void) { + if (interface == _UDSP_RGB) { + return; + } + if (ep_mode) { Updateframe_EPD(); return; @@ -1070,6 +1222,7 @@ void uDisplay::Updateframe(void) { void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { + if (ep_mode) { drawFastVLine_EPD(x, y, h, color); return; @@ -1084,6 +1237,29 @@ void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { if ((x >= _width) || (y >= _height)) return; if ((y + h - 1) >= _height) h = _height - y; + + if (interface == _UDSP_RGB) { + #ifdef USE_ESP32_S3 + if (cur_rot > 0) { + while (h--) { + drawPixel_RGB(x , y , color); + y++; + } + } else { + uint16_t *fb = rgb_fb; + fb += (int32_t)y * _width; + fb += x; + while (h--) { + *fb = color; + Cache_WriteBack_Addr((uint32_t)fb, 2); + fb+=_width; + y++; + } + } + #endif + return; + } + SPI_BEGIN_TRANSACTION SPI_CS_LOW @@ -1129,7 +1305,30 @@ void uDisplay::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { // Rudimentary clipping if((x >= _width) || (y >= _height)) return; - if((x+w-1) >= _width) w = _width-x; + if((x + w - 1) >= _width) w = _width - x; + + + if (interface == _UDSP_RGB) { +#ifdef USE_ESP32_S3 + if (cur_rot > 0) { + while (w--) { + drawPixel_RGB(x , y , color); + x++; + } + } else { + uint16_t *fb = rgb_fb; + fb += (int32_t)y * _width; + fb += x; + while (w--) { + *fb = color; + Cache_WriteBack_Addr((uint32_t)fb, 2); + fb++; + x++; + } + } + #endif + return; + } SPI_BEGIN_TRANSACTION @@ -1174,6 +1373,13 @@ void uDisplay::fillScreen(uint16_t color) { // fill a rectangle void uDisplay::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { + if (interface == _UDSP_RGB) { + for (uint32_t yp = y; yp < y + h; yp++) { + drawFastHLine(x, yp, w, color); + } + return; + } + if (ep_mode) { fillRect_EPD(x, y, w, h, color); @@ -1266,7 +1472,7 @@ void uDisplay::Splash(void) { void uDisplay::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { - if (bpp != 16) { + if (bpp != 16 || interface == _UDSP_RGB) { // just save params or update frame if (!x0 && !y0 && !x1 && !y1) { if (!ep_mode) { @@ -1282,6 +1488,10 @@ void uDisplay::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) return; } + if (interface == _UDSP_RGB) { + return; + } + if (!x0 && !y0 && !x1 && !y1) { SPI_CS_HIGH SPI_END_TRANSACTION @@ -1295,6 +1505,11 @@ void uDisplay::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) #define udisp_swap(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) ///< No-temp-var swap operation void uDisplay::setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + + if (interface == _UDSP_RGB) { + return; + } + x += x_addr_offs[cur_rot]; y += y_addr_offs[cur_rot]; @@ -1388,9 +1603,43 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) { not_swapped = !not_swapped; } - //Serial.printf("push %x - %d - %d - %d\n", (uint32_t)data, len, not_swapped,lvgl_param.data); + //Serial.printf("push %x - %d - %d - %d\n", (uint32_t)data, len, not_swapped, lvgl_param.data); if (not_swapped == false) { // called from LVGL bytes are swapped + if (interface == _UDSP_RGB) { +#ifdef USE_ESP32_S3 + if (cur_rot > 0) { + for (uint32_t y = seta_yp1; y < seta_yp2; y++) { + seta_yp1++; + for (uint32_t x = seta_xp1; x < seta_xp2; x++) { + uint16_t color = *data++; + color = color << 8 | color >> 8; + drawPixel_RGB(x, y, color); + len--; + if (!len) return; // failsafe - exist if len (pixel number) is exhausted + } + } + } else { + for (uint32_t y = seta_yp1; y < seta_yp2; y++) { + seta_yp1++; + uint16_t *fb = rgb_fb; + fb += (int32_t)y * _width; + fb += seta_xp1; + for (uint32_t x = seta_xp1; x < seta_xp2; x++) { + uint16_t color = *data++; + color = color << 8 | color >> 8; + *fb = color; + Cache_WriteBack_Addr((uint32_t)fb, 2); + fb++; + len--; + if (!len) return; // failsafe - exist if len (pixel number) is exhausted + } + } + } +#endif + return; + } + if (bpp != 16) { // lvgl_color_swap(data, len); -- no need to swap anymore, we have inverted the mask pushColorsMono(data, len, true); @@ -1464,6 +1713,36 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) { } } else { // called from displaytext, no byte swap, currently no dma here + if (interface == _UDSP_RGB) { +#ifdef USE_ESP32_S3 + if (cur_rot > 0) { + for (uint32_t y = seta_yp1; y < seta_yp2; y++) { + seta_yp1++; + for (uint32_t x = seta_xp1; x < seta_xp2; x++) { + drawPixel_RGB(x, y, *data++); + len--; + if (!len) return; // failsafe - exist if len (pixel number) is exhausted + } + } + } else { + for (uint32_t y = seta_yp1; y < seta_yp2; y++) { + seta_yp1++; + uint16_t *fb = rgb_fb; + fb += (int32_t)y * _width; + fb += seta_xp1; + for (uint32_t x = seta_xp1; x < seta_xp2; x++) { + *fb = *data++; + Cache_WriteBack_Addr((uint32_t)fb, 2); + fb++; + len--; + if (!len) return; // failsafe - exist if len (pixel number) is exhausted + } + } + } +#endif + return; + } + if (bpp != 16) { pushColorsMono(data, len); return; @@ -1512,8 +1791,49 @@ void uDisplay::WriteColor(uint16_t color) { } } +#ifdef USE_ESP32_S3 +void uDisplay::drawPixel_RGB(int16_t x, int16_t y, uint16_t color) { +int16_t w = _width, h = _height; + + if ((x < 0) || (x >= w) || (y < 0) || (y >= h)) { + return; + } + + // check rotation, move pixel around if necessary + switch (cur_rot) { + case 1: + renderer_swap(w, h); + renderer_swap(x, y); + x = w - x - 1; + break; + case 2: + x = w - x - 1; + y = h - y - 1; + break; + case 3: + renderer_swap(w, h); + renderer_swap(x, y); + y = h - y - 1; + break; + } + + uint16_t *fb = rgb_fb; + fb += (int32_t)y * w; + fb += x; + *fb = color; + Cache_WriteBack_Addr((uint32_t)fb, 2); + +} +#endif // USE_ESP32_S3 + void uDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) { +#ifdef USE_ESP32_S3 + if (interface == _UDSP_RGB) { + drawPixel_RGB(x, y, color); + return; + } +#endif if (ep_mode) { drawPixel_EPD(x, y, color); @@ -2172,7 +2492,7 @@ void uDisplay::SetFrameMemory( } #define IF_INVERT_COLOR 1 -#define renderer_swap(a, b) { int16_t t = a; a = b; b = t; } + /** * @brief: this draws a pixel by absolute coordinates. * this function won't be affected by the rotate parameter. @@ -2791,6 +3111,8 @@ uint32_t uDisplay::get_sr_touch(uint32_t _xp, uint32_t _xm, uint32_t _yp, uint32 } + + #if 0 void TFT_eSPI::startWrite(void) { diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 8d79bc8bc..25a27bab7 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -31,12 +31,19 @@ static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (pin static inline bool gpio_in(int_fast8_t pin) { return ((pin & 32) ? GPIO.in1.data : GPIO.in) & (1 << (pin & 31)); } static inline void gpio_hi(int_fast8_t pin) { if (pin >= 0) *get_gpio_hi_reg(pin) = 1 << (pin & 31); } // ESP_LOGI("LGFX", "gpio_hi: %d", pin); } static inline void gpio_lo(int_fast8_t pin) { if (pin >= 0) *get_gpio_lo_reg(pin) = 1 << (pin & 31); } // ESP_LOGI("LGFX", "gpio_lo: %d", pin); } -#endif +#include "esp_lcd_panel_interface.h" +#include "esp_lcd_panel_rgb.h" +#include "esp_pm.h" +#include "esp_lcd_panel_ops.h" +#include +#include +#endif // USE_ESP32_S3 #define _UDSP_I2C 1 #define _UDSP_SPI 2 #define _UDSP_PAR8 3 #define _UDSP_PAR16 4 +#define _UDSP_RGB 5 #define UDISP1_WHITE 1 #define UDISP1_BLACK 0 @@ -115,6 +122,39 @@ struct esp_lcd_i80_bus_t { size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source gdma_channel_handle_t dma_chan; // DMA channel handle }; + +// extract from esp-idf esp_lcd_rgb_panel.c +struct esp_rgb_panel_t +{ + esp_lcd_panel_t base; // Base class of generic lcd panel + int panel_id; // LCD panel ID + lcd_hal_context_t hal; // Hal layer object + size_t data_width; // Number of data lines (e.g. for RGB565, the data width is 16) + size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM + size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM + int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off" + intr_handle_t intr; // LCD peripheral interrupt handle + esp_pm_lock_handle_t pm_lock; // Power management lock + size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer + uint8_t *fb; // Frame buffer + size_t fb_size; // Size of frame buffer + int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color" + size_t resolution_hz; // Peripheral clock resolution + esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width) + gdma_channel_handle_t dma_chan; // DMA channel handle + esp_lcd_rgb_panel_frame_trans_done_cb_t on_frame_trans_done; // Callback, invoked after frame trans done + void *user_ctx; // Reserved user's data of callback functions + int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window + int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window + struct + { + unsigned int disp_en_level : 1; // The level which can turn on the screen by `disp_gpio_num` + unsigned int stream_mode : 1; // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done + unsigned int fb_in_psram : 1; // Whether the frame buffer is in PSRAM + } flags; + dma_descriptor_t dma_nodes[]; // DMA descriptor pool of size `num_dma_nodes` +}; + #endif @@ -278,6 +318,26 @@ class uDisplay : public Renderer { int8_t par_dbl[8]; int8_t par_dbh[8]; + int8_t de; + int8_t vsync; + int8_t hsync; + int8_t pclk; + + uint16_t hsync_polarity; + uint16_t hsync_front_porch; + uint16_t hsync_pulse_width; + uint16_t hsync_back_porch; + uint16_t vsync_polarity; + uint16_t vsync_front_porch; + uint16_t vsync_pulse_width; + uint16_t vsync_back_porch; + uint16_t pclk_active_neg; + + esp_lcd_panel_handle_t _panel_handle = NULL; + esp_rgb_panel_t *_rgb_panel; + uint16_t *rgb_fb; + + esp_lcd_i80_bus_handle_t _i80_bus = nullptr; gdma_channel_handle_t _dma_chan; lldesc_t *_dmadesc = nullptr; @@ -304,6 +364,7 @@ class uDisplay : public Renderer { uint8_t _align_data; void cs_control(bool level); uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym); + void drawPixel_RGB(int16_t x, int16_t y, uint16_t color); #endif #ifdef ESP32 diff --git a/tasmota/displaydesc/ST7262_rgb16_display.ini b/tasmota/displaydesc/ST7262_rgb16_display.ini new file mode 100644 index 000000000..413af0bb1 --- /dev/null +++ b/tasmota/displaydesc/ST7262_rgb16_display.ini @@ -0,0 +1,5 @@ +:H,ST7262,800,480,16,RGB,40,41,39,42,2,15,16,4,45,48,47,21,14,8,3,46,9,1,5,6,7,14 +:S,2,1,1,0,40,20 +:V,0,8,4,8,0,8,4,8,1 +:TI1,5a,*,*,-1,38 +# diff --git a/tasmota/tasmota_support/support_esp.ino b/tasmota/tasmota_support/support_esp.ino index 30b6129c9..935733baf 100644 --- a/tasmota/tasmota_support/support_esp.ino +++ b/tasmota/tasmota_support/support_esp.ino @@ -623,6 +623,9 @@ uint32_t ESP_getFreeHeap(void) { uint32_t ESP_getMaxAllocHeap(void) { // arduino returns IRAM but we want only DRAM +#ifdef RGB_DISPLAY + return ESP_getFreeHeap(); +#endif uint32_t free_block_size = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); if (free_block_size > 100) { free_block_size -= 100; } return free_block_size; @@ -1135,4 +1138,4 @@ uint32_t HwRandom(void) { last_ccount = ccount; return result ^ *(volatile uint32_t *)_RAND_ADDR; #undef _RAND_ADDR -} \ No newline at end of file +} diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 1f8596ec3..075a6c7b9 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -5152,7 +5152,7 @@ extern char *SML_GetSVal(uint32_t index); goto exit; } #endif // USE_TTGO_WATCH -#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_M5EPD47) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_GT911) if (!strncmp(lp, "wtch(", 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = Touch_Status(fvar); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino index 3a23b965e..69843572b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -36,7 +36,7 @@ \*******************************************************************************************/ -#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) || defined(SIMPLE_RES_TOUCH) +#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_GT911) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) || defined(SIMPLE_RES_TOUCH) #ifdef USE_DISPLAY_LVGL_ONLY #undef USE_TOUCH_BUTTONS @@ -72,6 +72,7 @@ typedef struct TSGlobal_t { TSGlobal_t TSGlobal; bool FT5206_found = false; +bool GT911_found = false; bool XPT2046_found = false; bool SRES_found = false; @@ -109,7 +110,7 @@ bool Touch_GetStatus(uint8_t* touches, uint16_t* x, uint16_t* y, uint8_t* gestur } uint32_t Touch_Status(int32_t sel) { - if (TSGlobal.external_ts || FT5206_found || XPT2046_found) { + if (TSGlobal.external_ts || FT5206_found || GT911_found || XPT2046_found || SRES_found) { switch (sel) { case 0: return TSGlobal.touched; @@ -196,7 +197,7 @@ bool FT5206_Touch_Init(TwoWire &i2c) { FT5206_found = false; FT5206_touchp = new FT5206_Class(); if (FT5206_touchp->begin(i2c, FT5206_address)) { - I2cSetActiveFound(FT5206_address, "FT5206"); + AddLog(LOG_LEVEL_INFO, PSTR("TI: FT5206")); FT5206_found = true; } //AddLog(LOG_LEVEL_INFO, PSTR("TS: FT5206 %d"),FT5206_found); @@ -216,11 +217,36 @@ int16_t FT5206_y() { } #endif // USE_FT5206 +#ifdef USE_GT911 +#include +// touch panel controller +GT911 *GT911_touchp; + +bool GT911_Touch_Init(TwoWire *i2c, int8_t irq_pin, int8_t rst_pin, uint16_t xs, uint16_t ys) { + GT911_found = false; + GT911_touchp = new GT911(); + if (ESP_OK == GT911_touchp->begin(i2c, irq_pin, rst_pin, xs, ys)) { + AddLog(LOG_LEVEL_INFO, PSTR("TI: GT911")); + GT911_found = true; + } + return GT911_found; +} + +void GT911_CheckTouch(void) { + GT911_touchp->update(); + TSGlobal.touched = !GT911_touchp->isFingerUp(); + if (TSGlobal.touched) { + TSGlobal.raw_touch_xp = GT911_touchp->readFingerX(0); + TSGlobal.raw_touch_yp = GT911_touchp->readFingerY(0); + } +} +#endif // USE_GT911 + + #ifdef USE_XPT2046 #include XPT2046_Touchscreen *XPT2046_touchp; - bool XPT2046_Touch_Init(uint16_t CS) { XPT2046_touchp = new XPT2046_Touchscreen(CS); XPT2046_found = XPT2046_touchp->begin(); @@ -266,6 +292,12 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { } #endif // USE_FT5206 +#ifdef USE_GT911 + if (GT911_found) { + GT911_CheckTouch(); + } +#endif // USE_FT5206 + #ifdef USE_XPT2046 if (XPT2046_found) { TSGlobal.touched = XPT2046_touched(); @@ -333,18 +365,17 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { } } -extern uint8_t GT911_found; #ifdef USE_TOUCH_BUTTONS void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) { #ifdef USE_FT5206 - if (FT5206_found) ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, val); + if (FT5206_found) ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index + 1, val); #endif #ifdef USE_XPT2046 - if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index+1, val); + if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index + 1, val); #endif // USE_XPT2046 #ifdef USE_GT911 - if (GT911_found) ResponseTime_P(PSTR(",\"GT911\":{\"%s%d\":\"%d\"}}"), cp, index+1, val); + if (GT911_found) ResponseTime_P(PSTR(",\"GT911\":{\"%s%d\":\"%d\"}}"), cp, index + 1, val); #endif // USE_XPT2046 MqttPublishTeleSensor(); } @@ -466,7 +497,7 @@ bool Xdrv55(uint32_t function) { case FUNC_INIT: break; case FUNC_EVERY_100_MSECOND: - if (FT5206_found || XPT2046_found || SRES_found) { + if (FT5206_found || XPT2046_found || GT911_found || SRES_found) { Touch_Check(TS_RotConvert); } break; diff --git a/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino b/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino index 3a24870d4..01dd6495a 100644 --- a/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino +++ b/tasmota/tasmota_xdsp_display/xdsp_17_universal.ino @@ -33,6 +33,8 @@ uint8_t ctouch_counter; extern FS *ffsp; #endif +#undef GT911_address +#define GT911_address 0x5D enum {GPIO_DP_RES=GPIO_SENSOR_END-1,GPIO_DP_CS,GPIO_DP_RS,GPIO_DP_WR,GPIO_DP_RD,GPIO_DPAR0,GPIO_DPAR1,GPIO_DPAR2,GPIO_DPAR3,GPIO_DPAR4,GPIO_DPAR5,GPIO_DPAR6,GPIO_DPAR7,GPIO_DPAR8,GPIO_DPAR9,GPIO_DPAR10,GPIO_DPAR11,GPIO_DPAR12,GPIO_DPAR13,GPIO_DPAR14,GPIO_DPAR15}; @@ -231,8 +233,21 @@ int8_t cs; } } + uint16_t xs, ys; + // we need screen size for gt911 touch controler + cp = strstr(ddesc, ":H,"); + if (cp) { + cp += 3; + cp = strchr(cp, ','); + cp++; + xs = strtol(cp, &cp, 10); + cp++; + ys = strtol(cp, &cp, 10); + } + #ifdef CONFIG_IDF_TARGET_ESP32S3 int8_t xp, xm, yp, ym; + cp = strstr(ddesc, "PAR,"); if (cp) { cp += 4; @@ -284,7 +299,7 @@ int8_t cs; udisp = new uDisplay(ddesc); // checck for touch option TI1 or TI2 -#ifdef USE_FT5206 +#if defined(USE_FT5206) || defined(USE_GT911) cp = strstr(ddesc, ":TI"); if (cp) { uint8_t wire_n = 1; @@ -293,9 +308,21 @@ int8_t cs; cp += 2; uint8_t i2caddr = strtol(cp, &cp, 16); - int8_t scl, sda; + int8_t scl, sda, irq = -1, rst = -1; scl = replacepin(&cp, Pin(GPIO_I2C_SCL, wire_n)); sda = replacepin(&cp, Pin(GPIO_I2C_SDA, wire_n)); + if (*(cp - 1) == ',') { + irq = strtol(cp, &cp, 10); + } else { + irq = -1; + } + if (*cp == ',') { + cp++; + rst = strtol(cp, &cp, 10); + } else { + rst = -1; + } + if (wire_n == 0) { I2cBegin(sda, scl); } @@ -304,26 +331,54 @@ int8_t cs; I2c2Begin(sda, scl, 400000); } if (I2cSetDevice(i2caddr, wire_n)) { - I2cSetActiveFound(i2caddr, "FT5206", wire_n); + if (i2caddr == GT911_address) { + I2cSetActiveFound(i2caddr, "GT911", wire_n); + } else { + I2cSetActiveFound(i2caddr, "FT5206", wire_n); + } } #endif // ESP32 #ifdef ESP8266 //AddLog(LOG_LEVEL_INFO, PSTR("DSP: touch %x, %d, %d, %d!"), i2caddr, wire_n, scl, sda); if (I2cSetDevice(i2caddr)) { - I2cSetActiveFound(i2caddr, "FT5206"); + if (i2caddr == GT911_address) { + I2cSetActiveFound(i2caddr, "GT911"); + } else { + I2cSetActiveFound(i2caddr, "FT5206"); + } } #endif // ESP8266 // start digitizer #ifdef ESP32 - if (!wire_n) FT5206_Touch_Init(Wire); - else FT5206_Touch_Init(Wire1); + if (i2caddr == GT911_address) { +#ifdef USE_GT911 + if (!wire_n) GT911_Touch_Init(&Wire, irq, rst, xs, ys); + else GT911_Touch_Init(&Wire1, irq, rst, xs, ys); +#endif + } else { +#ifdef USE_FT5206 + if (!wire_n) FT5206_Touch_Init(Wire); + else FT5206_Touch_Init(Wire1); +#endif + } + #else + + if (i2caddr == GT911_address) { +#ifdef USE_GT911 + if (!wire_n) GT911_Touch_Init(&Wire, irq, rst, xs, ys); +#endif + } else { +#ifdef USE_FT5206 if (!wire_n) FT5206_Touch_Init(Wire); +#endif + } #endif // ESP32 + } -#endif // USE_FT5206 +#endif // USE_FT5206 || GT911 #ifdef USE_XPT2046 cp = strstr(ddesc, ":TS,");