From 780940d5d0df6d4471a11ab3d0f0dbdefa23b657 Mon Sep 17 00:00:00 2001 From: gemu Date: Mon, 22 Jan 2024 18:21:40 +0100 Subject: [PATCH] Utouch update (#20561) * toched return int16 * add XPT and more opcodes * add guesture * increase code buffer --- .../src/renderer.cpp | 2 +- .../Display_Renderer-gemu-1.0/src/renderer.h | 2 +- lib/lib_display/UDisplay/uDisplay.cpp | 318 +++++++++++++++--- lib/lib_display/UDisplay/uDisplay.h | 43 ++- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 2 +- tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino | 7 +- 6 files changed, 312 insertions(+), 62 deletions(-) diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp index 0bc75395f..f44500c51 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.cpp @@ -627,7 +627,7 @@ bool Renderer::utouch_Init(char **name) { return false; } -bool Renderer::touched(void) { +uint16_t Renderer::touched(void) { return false; } diff --git a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h index a63c4a93f..7ef7d86ab 100644 --- a/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h +++ b/lib/lib_display/Display_Renderer-gemu-1.0/src/renderer.h @@ -93,7 +93,7 @@ public: virtual void ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode); virtual uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym); virtual bool utouch_Init(char **); - virtual bool touched(void); + virtual uint16_t touched(void); virtual int16_t getPoint_x(); virtual int16_t getPoint_y(); diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index f46032dac..cd671c659 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -587,17 +587,13 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { } else if (*lp1 == 'S') { // spi mode lp1++; - uint8_t ut_mode = *lp1 & 0xf; + ut_spi_nr = *lp1 & 0xf; lp1 += 2; - ut_reset = -1; - ut_irq = -1; ut_spi_cs = next_val(&lp1); ut_reset = next_val(&lp1); ut_irq = next_val(&lp1); - // assume displays SPI bus pinMode(ut_spi_cs, OUTPUT); digitalWrite(ut_spi_cs, HIGH); - ut_spiSettings = SPISettings(2000000, MSBFIRST, SPI_MODE0); } else { // simple resistive touch @@ -921,6 +917,17 @@ uint16_t index = 0; delay_arg(args); } } else { + if (spi_dc == -2) { + // pseudo opcodes + switch (iob) { + case UDSP_WRITE_16: + break; + case UDSP_READ_DATA: + break; + case UDSP_READ_STATUS: + break; + } + } ulcd_command(iob); uint8_t args = dsp_cmds[cmd_offset++]; index++; @@ -1913,13 +1920,21 @@ bool uDisplay::utouch_Init(char **name) { delay(10); } if (ut_irq >= 0) { + pinMode(ut_irq, INPUT ); attachInterrupt(ut_irq, ut_touch_irq, FALLING); } + if (ut_spi_nr == spi_nr) { + ut_spi = uspi; + } else { + // not yet + ut_spi = nullptr; + } + return ut_execute(ut_init_code); } -bool uDisplay::touched(void) { +uint16_t uDisplay::touched(void) { if (ut_irq >= 0) { if (!ut_irq_flg) { return false; @@ -2524,7 +2539,7 @@ void uDisplay::dim10(uint8_t dim, uint16_t dim_gamma) { // dimmer with } // the cases are PSEUDO_OPCODES from MODULE_DESCRIPTOR -// and may be exapnded with more opcodes +// and may be expanded with more opcodes void uDisplay::TS_RotConvert(int16_t *x, int16_t *y) { int16_t temp; @@ -2588,22 +2603,38 @@ char *uDisplay::devname(void) { #ifdef USE_UNIVERSAL_TOUCH -uint16_t uDisplay::ut_par(char **lp, uint32_t mode) { +float CharToFloat(const char *str); + +uint32_t uDisplay::ut_par(char **lp, uint32_t mode) { char *cp = *lp; while (*cp != ' ') { + if (!cp) break; cp++; } cp++; - uint16_t result; + uint32_t result; if (!mode) { + // hex result = strtol(cp, &cp, 16); - } else { + } else if (mode == 1) { + // word result = strtol(cp, &cp, 10); + } else { + // float as 32bit integer + float fval = CharToFloat(cp); + result = *(uint32_t*)&fval; + while (*cp) { + if (*cp == ' ' || *cp =='\n') { + break; + } + cp++; + } } *lp = cp; return result; } +// translate pseudo opcodes to tokens void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { char *cp = *sp; uint16_t wval; @@ -2611,6 +2642,16 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { if (*cp == ':' || *cp == '#') { break; } + if (*cp == ';') { + // skip comment line + while (*cp) { + if (*cp == '\n') { + cp++; + break; + } + cp++; + } + } if (!strncmp(cp, "RDWM", 4)) { // read word many *ut_code++ = UT_RDWM; @@ -2663,6 +2704,12 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { // return when true *ut_code++ = UT_RTT; size -= 1; + } else if (!strncmp(cp, "MVB", 3)) { + // move + *ut_code++ = UT_MVB; + *ut_code++ = ut_par(&cp, 1); + *ut_code++ = ut_par(&cp, 1); + size -= 3; } else if (!strncmp(cp, "MV", 2)) { // move *ut_code++ = UT_MV; @@ -2691,13 +2738,36 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { } else if (!strncmp(cp, "AND", 3)) { *ut_code++ = UT_AND; wval = ut_par(&cp, 0); - *ut_code++ = wval>>8; + *ut_code++ = wval >> 8; + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "SCL", 3)) { + *ut_code++ = UT_SCALE; + wval = ut_par(&cp, 1); + *ut_code++ = wval >> 8; + *ut_code++ = wval; + uint32_t lval = ut_par(&cp, 2); + *ut_code++ = lval >> 24; + *ut_code++ = lval >> 16; + *ut_code++ = lval >> 8; + *ut_code++ = lval; + size -= 7; + } else if (!strncmp(cp, "LIM", 3)) { + *ut_code++ = UT_LIM; + wval = ut_par(&cp, 1); + *ut_code++ = wval >> 8; *ut_code++ = wval; size -= 3; } else if (!strncmp(cp, "GSRT", 4)) { *ut_code++ = UT_GSRT; wval = ut_par(&cp, 1); - *ut_code++ = wval>>8; + *ut_code++ = wval >> 8; + *ut_code++ = wval; + size -= 3; + } else if (!strncmp(cp, "XPT", 3)) { + *ut_code++ = UT_XPT; + wval = ut_par(&cp, 1); + *ut_code++ = wval >> 8; *ut_code++ = wval; size -= 3; } else if (!strncmp(cp, "DBG", 3)) { @@ -2710,6 +2780,9 @@ void uDisplay::ut_trans(char **sp, uint8_t *ut_code, int32_t size) { break; } + + + cp++; } *ut_code++ = UT_END; @@ -2735,16 +2808,20 @@ uint8_t *uDisplay::ut_rd(uint8_t *iop, uint32_t len, uint32_t amode) { } } else { // spi mode - uint16_t val = *iop++; - digitalWrite(ut_spi_cs, LOW); - if (spi_nr <= 2) { - uspi->beginTransaction(ut_spiSettings); - val = uspi->transfer16(val); - uspi->endTransaction(); - ut_array[0] = val << 8; - ut_array[1] = val; + if (amode == 1) { + uint16_t val = *iop++; + uint16_t len = *iop++; + if (ut_spi) { + digitalWrite(ut_spi_cs, LOW); + ut_spi->beginTransaction(ut_spiSettings); + ut_spi->transfer(val); + val = ut_spi->transfer16(0); + ut_spi->endTransaction(); + ut_array[len] = val << 8; + ut_array[len + 1] = val; + digitalWrite(ut_spi_cs, HIGH); + } } - digitalWrite(ut_spi_cs, HIGH); } return iop; } @@ -2765,6 +2842,59 @@ uint8_t *uDisplay::ut_wr(uint8_t *iop, uint32_t amode) { return iop; } + +int16_t uDisplay::besttwoavg( int16_t x , int16_t y , int16_t z ) { + int16_t da, db, dc; + int16_t reta = 0; + if ( x > y ) da = x - y; else da = y - x; + if ( x > z ) db = x - z; else db = z - x; + if ( z > y ) dc = z - y; else dc = y - z; + + if ( da <= db && da <= dc ) reta = (x + y) >> 1; + else if ( db <= da && db <= dc ) reta = (x + z) >> 1; + else reta = (y + z) >> 1; + + return (reta); +} + +uint16_t uDisplay::ut_XPT2046(uint16_t z_th) { + uint16_t result = 0; + if (ut_spi) { + int16_t data[6]; + ut_spi->beginTransaction(ut_spiSettings); + digitalWrite(ut_spi_cs, LOW); + ut_spi->transfer(0xB1 /* Z1 */); + int16_t z1 = ut_spi->transfer16(0xC1 /* Z2 */) >> 3; + int16_t z = z1 + 4095; + int16_t z2 = ut_spi->transfer16(0x91 /* X */) >> 3; + z -= z2; + if (z >= z_th) { + ut_spi->transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy + data[0] = ut_spi->transfer16(0xD1 /* Y */) >> 3; + data[1] = ut_spi->transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements + data[2] = ut_spi->transfer16(0xD1 /* Y */) >> 3; + data[3] = ut_spi->transfer16(0x91 /* X */) >> 3; + result = 1; + } + else { + data[0] = data[1] = data[2] = data[3] = 0; + } + data[4] = ut_spi->transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down + data[5] = ut_spi->transfer16(0) >> 3; + digitalWrite(ut_spi_cs, HIGH); + ut_spi->endTransaction(); + + uint16_t x = besttwoavg( data[0], data[2], data[4] ); + uint16_t y = besttwoavg( data[1], data[3], data[5] ); + + ut_array[0] = x >> 8; + ut_array[1] = x; + ut_array[2] = y >> 8; + ut_array[3] = y; + } + return result; +} + int16_t uDisplay::ut_execute(uint8_t *ut_code) { int16_t result = 0; uint8_t iob, len; @@ -2777,46 +2907,69 @@ uint16_t wval; // read 1 byte ut_code = ut_rd(ut_code, 1, 1); break; + case UT_RDM: // read multiple bytes ut_code = ut_rd(ut_code, 2, 1); break; + case UT_RDW: // read 1 byte ut_code = ut_rd(ut_code, 1, 2); break; + case UT_RDWM: // read multiple bytes ut_code = ut_rd(ut_code, 2, 2); break; + case UT_WR: ut_code = ut_wr(ut_code, 1); break; + case UT_WRW: ut_code = ut_wr(ut_code, 2); break; + case UT_CP: // compare iob = *ut_code++; result = (iob == ut_array[0]); break; + case UT_CPR: // compare iob = *ut_code++; result = (iob == result); break; + case UT_RTF: // return when false if (result == 0) { return false; } break; + case UT_RTT: // return when true if (result > 0) { return false; } - break; + break; + + case UT_MVB: + // move byte from index to high or low result + wval = *ut_code++; + iob = *ut_code++; + if (wval == 0) { + result &= 0xff00; + result |= ut_array[iob]; + } else { + result &= 0x00ff; + result |= (ut_array[iob] << 8); + } + break; + case UT_MV: // move // source @@ -2835,16 +2988,42 @@ uint16_t wval; } result &= 0xfff; break; - case UT_AND: + + case UT_AND: // and wval = *ut_code++ << 8; wval |= *ut_code++; result &= wval; break; + + case UT_SCALE: + { + wval = *ut_code++ << 8; + wval |= *ut_code++; + result -= wval; + uint32_t lval = (uint32_t)*ut_code++ << 24; + lval |= (uint32_t)*ut_code++ << 16; + lval |= (uint32_t)*ut_code++ << 8; + lval |= (uint32_t)*ut_code++; + float fval = *(float*)&lval; + fval *= (float)result; + result = fval; + } + break; + + case UT_LIM: + wval = *ut_code++ << 8; + wval |= *ut_code++; + if (result > wval) { + result = wval; + } + break; + case UT_RT: // result return result; break; + case UT_GSRT: #ifdef USE_ESP32_S3 { uint32_t val = get_sr_touch(SIMPLERS_XP, SIMPLERS_XM, SIMPLERS_YP, SIMPLERS_YM); @@ -2867,12 +3046,20 @@ uint16_t wval; } #endif // USE_ESP32_S3 break; + + case UT_XPT: + wval = *ut_code++ << 8; + wval |= *ut_code++; + result = ut_XPT2046(wval); + break; + case UT_DBG: // debug show result //Serial.printf("UTDBG: %d\n", result); wval = *ut_code++; AddLog(LOG_LEVEL_INFO, PSTR("UTDBG %d: %02x : %02x,%02x,%02x,%02x"), wval, result, ut_array[0], ut_array[1], ut_array[2], ut_array[3]); break; + case UT_END: break; } @@ -2937,38 +3124,57 @@ uint32_t uDisplay::next_hex(char **sp) { // we use our own hardware driver for 9 bit spi void uDisplay::hw_write9(uint8_t val, uint8_t dc) { - uint32_t regvalue = val >> 1; - if (dc) regvalue |= 0x80; - else regvalue &= 0x7f; - if (val & 1) regvalue |= 0x8000; - - REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); - REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1); - uint32_t *dp = (uint32_t*)SPI_W0_REG(3); - *dp = regvalue; - REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); - while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); + if (spi_dc < -1) { + // RA8876 mode + if (!dc) { + uspi->write(RA8876_CMD_WRITE); + uspi->write(val); + } else { + uspi->write(RA8876_DATA_WRITE); + uspi->write(val); + } + } else { + uint32_t regvalue = val >> 1; + if (dc) regvalue |= 0x80; + else regvalue &= 0x7f; + if (val & 1) regvalue |= 0x8000; + REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); + REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1); + uint32_t *dp = (uint32_t*)SPI_W0_REG(3); + *dp = regvalue; + REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); + while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); + } } #else #include "spi_register.h" void uDisplay::hw_write9(uint8_t val, uint8_t dc) { - uint32_t regvalue; - uint8_t bytetemp; - if (!dc) { - bytetemp = (val>> 1) & 0x7f; + if (spi_dc < -1) { + // RA8876 mode + if (!dc) { + uspi->write(RA8876_CMD_WRITE); + uspi->write(val); + } else { + uspi->write(RA8876_DATA_WRITE); + uspi->write(val); + } } else { - bytetemp = (val >> 1) | 0x80; + uint32_t regvalue; + uint8_t bytetemp; + if (!dc) { + bytetemp = (val>> 1) & 0x7f; + } else { + bytetemp = (val >> 1) | 0x80; + } + regvalue = ((8 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | ((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit + if (val & 0x01) regvalue |= BIT15; //write the 9th bit + while (READ_PERI_REG(SPI_CMD(1)) & SPI_USR); //waiting for spi module available + WRITE_PERI_REG(SPI_USER2(1), regvalue); //write command and command length into spi reg + SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR); //transmission start } - - regvalue = ((8 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) | ((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit - if (val & 0x01) regvalue |= BIT15; //write the 9th bit - while (READ_PERI_REG(SPI_CMD(1)) & SPI_USR); //waiting for spi module available - WRITE_PERI_REG(SPI_USER2(1), regvalue); //write command and command length into spi reg - SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR); //transmission start - } #endif @@ -2985,6 +3191,26 @@ void USECACHE uDisplay::write8(uint8_t val) { } } +uint8_t uDisplay::writeReg16(uint8_t reg, uint16_t wval) { + hw_write9(reg, 0); + hw_write9(wval, 1); + hw_write9(reg + 1, 0); + hw_write9(wval >> 8, 1); + return 0; +} + +uint8_t uDisplay::readData(void) { + uspi->write(RA8876_DATA_READ); + uint8_t val = uspi->transfer(0); + return val; +} + +uint8_t uDisplay::readStatus(void) { + uspi->write(RA8876_STATUS_READ); + uint8_t val = uspi->transfer(0); + return val; +} + void uDisplay::write8_slow(uint8_t val) { for (uint8_t bit = 0x80; bit; bit >>= 1) { GPIO_CLR_SLOW(spi_clk); diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 21e2eb6f3..9878e865d 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -17,6 +17,25 @@ #endif // ESP_IDF_VERSION_MAJOR >= 5 #endif +enum { + UT_RD,UT_RDM,UT_CP,UT_RTF,UT_MV,UT_MVB,UT_RT,UT_RTT,UT_RDW,UT_RDWM,UT_WR,UT_WRW,UT_CPR,UT_AND,UT_SCALE,UT_LIM,UT_DBG,UT_GSRT,UT_XPT,UT_END +}; + +#define RA8876_DATA_WRITE 0x80 +#define RA8876_DATA_READ 0xC0 +#define RA8876_CMD_WRITE 0x00 +#define RA8876_STATUS_READ 0x40 + +#define UDSP_WRITE_16 0xf0 +#define UDSP_READ_DATA 0xf1 +#define UDSP_READ_STATUS 0xf2 + + +#define SIMPLERS_XP par_dbl[1] +#define SIMPLERS_XM par_cs +#define SIMPLERS_YP par_rs +#define SIMPLERS_YM par_dbl[0] + #ifdef USE_ESP32_S3 #include #include "esp_private/gdma.h" @@ -101,14 +120,7 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR }; #define GPIO_SET(A) GPIO.out_w1ts = (1 << A) #endif -enum { - UT_RD,UT_RDM,UT_CP,UT_RTF,UT_MV,UT_RT,UT_RTT,UT_RDW,UT_RDWM,UT_WR,UT_WRW,UT_CPR,UT_AND,UT_DBG,UT_GSRT,UT_END -}; -#define SIMPLERS_XP par_dbl[1] -#define SIMPLERS_XM par_cs -#define SIMPLERS_YP par_rs -#define SIMPLERS_YM par_dbl[0] #define GPIO_CLR_SLOW(A) digitalWrite(A, LOW) @@ -202,7 +214,7 @@ class uDisplay : public Renderer { #ifdef USE_UNIVERSAL_TOUCH // universal touch driver bool utouch_Init(char **name); - bool touched(void); + uint16_t touched(void); int16_t getPoint_x(); int16_t getPoint_y(); #endif // USE_UNIVERSAL_TOUCH @@ -229,6 +241,9 @@ class uDisplay : public Renderer { void write16(uint16_t val); void write32(uint32_t val); void spi_data9(uint8_t d, uint8_t dc); + uint8_t readData(void); + uint8_t readStatus(void); + uint8_t writeReg16(uint8_t reg, uint16_t wval); void WriteColor(uint16_t color); void SetLut(const unsigned char* lut); void SetLuts(void); @@ -432,22 +447,26 @@ class uDisplay : public Renderer { // universal touch driver void ut_trans(char **sp, uint8_t *ut_code, int32_t size); int16_t ut_execute(uint8_t *ut_code); - uint16_t ut_par(char **cp, uint32_t mode); + uint32_t ut_par(char **cp, uint32_t mode); uint8_t *ut_rd(uint8_t *io, uint32_t len, uint32_t amode); uint8_t *ut_wr(uint8_t *io, uint32_t amode); - uint32_t ut_result; + uint16_t ut_XPT2046(uint16_t zh); + int16_t besttwoavg( int16_t x , int16_t y , int16_t z ); + uint8_t ut_array[16]; uint8_t ut_i2caddr; uint8_t ut_spi_cs; int8_t ut_reset; int8_t ut_irq; + uint8_t ut_spi_nr; TwoWire *ut_wire; + SPIClass *ut_spi; SPISettings ut_spiSettings; char ut_name[8]; uint8_t ut_init_code[32]; uint8_t ut_touch_code[32]; - uint8_t ut_getx_code[16]; - uint8_t ut_gety_code[16]; + uint8_t ut_getx_code[20]; + uint8_t ut_gety_code[20]; #endif // USE_UNIVERSAL_TOUCH }; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 76903985e..a3753a8ca 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -5875,7 +5875,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_UNIVERSAL_TOUCH) || defined(USE_GT911) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_UNIVERSAL_TOUCH) || defined(USE_CST816S) || defined(SIMPLE_RES_TOUCH) || defined(USE_GT911) if (!strncmp_XP(lp, XPSTR("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 1801fb3d6..9a82e7eb8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_55_touch.ino @@ -254,8 +254,13 @@ void utouch_Touch_Init() { bool utouch_touched() { if (renderer) { - return renderer->touched(); + uint16 status = renderer->touched(); + if (status & 1) { + TSGlobal.gesture = status >> 8; + return true; + } } + return false; } int16_t utouch_x() { if (renderer) {