diff --git a/lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp b/lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp index 7fd4f0043..ecf775c75 100644 --- a/lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp +++ b/lib/lib_display/Adafruit_SH1106-gemu-1.0/Adafruit_SH1106.cpp @@ -72,6 +72,8 @@ void Adafruit_SH1106::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) { //fillScreen(BLACK); fillScreen(BLACK); Updateframe(); + + disp_bpp = -1; //} } diff --git a/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp index 28459cad9..aa5ab4bf3 100644 --- a/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp +++ b/lib/lib_display/Adafruit_SSD1306-1.3.0-gemu-1.1/Adafruit_SSD1306.cpp @@ -604,6 +604,8 @@ void Adafruit_SSD1306::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) setCursor(0,0); fillScreen(BLACK); Updateframe(); + + disp_bpp = -1; //} } 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 96125f14d..4146826ab 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 @@ -49,7 +49,7 @@ Adafruit_GFX(x, y) { #ifdef USE_EPD_FONTS selected_font = &Font12; #endif - + disp_bpp = 16; } uint16_t Renderer::GetColorFromIndex(uint8_t index) { 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 d986db909..f94b65393 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 @@ -78,6 +78,7 @@ public: pwr_cb pwr_cbp = 0; dim_cb dim_cbp = 0; LVGL_PARAMS lvgl_param; + int8_t disp_bpp; private: void DrawCharAt(int16_t x, int16_t y, char ascii_char,int16_t colored); inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline)); diff --git a/lib/lib_display/Epaper_29-gemu-1.0/epd2in9.cpp b/lib/lib_display/Epaper_29-gemu-1.0/epd2in9.cpp index d1c3ce2bb..434a14b89 100644 --- a/lib/lib_display/Epaper_29-gemu-1.0/epd2in9.cpp +++ b/lib/lib_display/Epaper_29-gemu-1.0/epd2in9.cpp @@ -74,6 +74,8 @@ void Epd::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) { setTextColor(WHITE,BLACK); setCursor(0,0); fillScreen(BLACK); + + disp_bpp = 1; } void Epd::Begin(int16_t cs,int16_t mosi,int16_t sclk) { diff --git a/lib/lib_display/Epaper_42-gemu-1.0/epd4in2.cpp b/lib/lib_display/Epaper_42-gemu-1.0/epd4in2.cpp index 9eae4377e..b9766b27a 100644 --- a/lib/lib_display/Epaper_42-gemu-1.0/epd4in2.cpp +++ b/lib/lib_display/Epaper_42-gemu-1.0/epd4in2.cpp @@ -86,6 +86,8 @@ void Epd42::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) { setTextColor(WHITE,BLACK); setCursor(0,0); fillScreen(BLACK); + + disp_bpp = 1; } void Epd42::Begin(int16_t cs,int16_t mosi,int16_t sclk) { diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index 83adde5ae..c252395df 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -122,7 +122,8 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { setwidth(gxs); gys = next_val(&lp1); setheight(gys); - bpp = next_val(&lp1); + disp_bpp = next_val(&lp1); + bpp = abs(disp_bpp); if (bpp == 1) { col_type = uCOLOR_BW; } else { @@ -373,15 +374,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { Renderer *uDisplay::Init(void) { - if (reset >= 0) { - pinMode(reset, OUTPUT); - digitalWrite(reset, HIGH); - delay(50); - digitalWrite(reset, LOW); - delay(50); - digitalWrite(reset, HIGH); - delay(200); - } + if (interface == _UDSP_I2C) { if (wire_n == 0) { @@ -486,6 +479,16 @@ Renderer *uDisplay::Init(void) { } #endif // ESP32 + if (reset >= 0) { + pinMode(reset, OUTPUT); + digitalWrite(reset, HIGH); + delay(50); + digitalWrite(reset, LOW); + delay(50); + digitalWrite(reset, HIGH); + delay(200); + } + spiSettings = SPISettings((uint32_t)spi_speed*1000000, MSBFIRST, SPI_MODE3); uint16_t index = 0; @@ -948,7 +951,7 @@ for(y=h; y>0; y--) { void uDisplay::Splash(void) { if (splash_font < 0) return; - + if (ep_mode) { Updateframe(); delay(lut3time * 10); diff --git a/lib/libesp32_epdiy/src/epd4in7.cpp b/lib/libesp32_epdiy/src/epd4in7.cpp index 2c3aef3b9..bc0882e0f 100644 --- a/lib/libesp32_epdiy/src/epd4in7.cpp +++ b/lib/libesp32_epdiy/src/epd4in7.cpp @@ -55,19 +55,20 @@ uint16_t Epd47::GetColorFromIndex(uint8_t index) { Epd47::Epd47(int16_t dwidth, int16_t dheight) : Renderer(dwidth, dheight) { width = dwidth; height = dheight; + disp_bpp = 4; } int32_t Epd47::Init(void) { epd_init(EPD_LUT_1K); hl = epd_hl_init(WAVEFORM); epd47_buffer = epd_hl_get_framebuffer(&hl); + framebuffer = epd47_buffer; lvgl_param.fluslines = 10; return 0; } void Epd47::DisplayInit(int8_t p, int8_t size, int8_t rot, int8_t font) { - if (p == DISPLAY_INIT_MODE) { epd_poweron(); epd_clear(); diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 2971bb03c..ef6e3429b 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -69,6 +69,9 @@ keywords if then else endif, or, and are better readable for beginners (others m #define MAX_SARRAY_NUM 32 #endif +#include +extern Renderer *renderer; + uint32_t EncodeLightId(uint8_t relay_id); uint32_t DecodeLightId(uint32_t hue_id); @@ -2352,7 +2355,7 @@ chknext: goto exit; } if (!strncmp(vname, "fsm", 3)) { - fvar=glob_script_mem.script_sd_found; + fvar=(uint32_t)ufsp; //card_init(); goto exit; } @@ -3339,7 +3342,7 @@ chknext: goto exit; } #endif // USE_TTGO_WATCH -#if defined(USE_FT5206) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) if (!strncmp(vname, "wtch(", 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = Touch_Status(fvar); @@ -5323,8 +5326,8 @@ void HandleScriptConfiguration(void) { WSContentSend_P(HTTP_FORM_SCRIPT1b); #ifdef USE_SCRIPT_FATFS - if (glob_script_mem.script_sd_found) { - WSContentSend_P(HTTP_FORM_SCRIPT1d); + if (ufsp) { + //WSContentSend_P(HTTP_FORM_SCRIPT1d); if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c, 1, glob_script_mem.flink[0]); if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c, 2, glob_script_mem.flink[1]); } @@ -6489,10 +6492,12 @@ char buff[512]; // screen copy #define fileHeaderSize 14 #define infoHeaderSize 40 - if (buffer) { - uint8_t *bp = buffer; + + if (renderer && renderer->framebuffer) { + uint8_t *bp = renderer->framebuffer; uint8_t *lbuf = (uint8_t*)special_malloc(Settings.display_width * 3 + 2); if (!lbuf) return; + int8_t bpp = renderer->disp_bpp; uint8_t *lbp; uint8_t fileHeader[fileHeaderSize]; createBitmapFileHeader(Settings.display_height , Settings.display_width , fileHeader); @@ -6500,23 +6505,58 @@ char buff[512]; uint8_t infoHeader[infoHeaderSize]; createBitmapInfoHeader(Settings.display_height, Settings.display_width, infoHeader ); Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize); - for (uint32_t lins = 0; lins= 0 ; lins--) { + lbp = lbuf; + for (uint32_t cols = 0; cols < Settings.display_width; cols ++) { + uint8_t pixel = 0; + if (bp[cols + (lins / 8) * Settings.display_width] & (1 << (lins & 7))) { + pixel = 0xff; + } + *lbp++ = pixel; + *lbp++ = pixel; + *lbp++ = pixel; + } + Webserver->client().write((const char*)lbuf, Settings.display_width * 3); + } + } else { + for (uint32_t lins = 0; lins> 4; + } else { + pixel = *bp & 0xf; + } + pixel *= 15; + *--lbp = pixel; + *--lbp = pixel; + *--lbp = pixel; + } + bp++; + } + } else { + for (uint32_t cols = 0; cols < Settings.display_width; cols += 8) { + uint8_t bits = 0x80; + while (bits) { + if (!((*bp) & bits)) { + *--lbp = 0xff; + *--lbp = 0xff; + *--lbp = 0xff; + } else { + *--lbp = 0; + *--lbp = 0; + *--lbp = 0; + } + bits = bits>>1; + } + bp++; } - bits = bits>>1; } - bp++; } Webserver->client().write((const char*)lbuf, Settings.display_width * 3); } diff --git a/tasmota/xdsp_16_esp32_epaper_47.ino b/tasmota/xdsp_16_esp32_epaper_47.ino index 990c92fdf..d92689807 100644 --- a/tasmota/xdsp_16_esp32_epaper_47.ino +++ b/tasmota/xdsp_16_esp32_epaper_47.ino @@ -67,6 +67,11 @@ void EpdInitDriver47(void) { bg_color = EPD47_WHITE; color_type = COLOR_COLOR; +#ifdef USE_TOUCH_BUTTONS + // start digitizer + EPD47_Touch_Init(); +#endif // USE_TOUCH_BUTTONS + epd47_init_done = true; AddLog(LOG_LEVEL_INFO, PSTR("DSP: E-Paper 4.7")); } @@ -75,6 +80,198 @@ void EpdInitDriver47(void) { /*********************************************************************************************/ +#ifdef USE_TOUCH_BUTTONS + +#define TOUCH_SLAVE_ADDRESS 0x5a +class TouchClass { + + typedef struct { + uint8_t id; + uint8_t state; + uint16_t x; + uint16_t y; + } TouchData_t; + +public: + bool begin(TwoWire &port = Wire, uint8_t addr = TOUCH_SLAVE_ADDRESS); + uint8_t scanPoint(); + void getPoint(int16_t &x, int16_t &y, uint8_t index); +// void sleep(void); +// void wakeup(void); + TouchData_t data[5]; + +private: + void clearFlags(void); + void readBytes(uint8_t *data, uint8_t nbytes); + uint8_t _address; + bool initialization = false; + TwoWire *_i2cPort; +}; + +void TouchClass::readBytes(uint8_t *data, uint8_t nbytes) { + _i2cPort->beginTransmission(_address); // Initialize the Tx buffer + _i2cPort->write(data, 2); // Put data in Tx buffer + if (0 != _i2cPort->endTransmission()) { + Serial.println("readBytes error!"); + } + uint8_t i = 0; + _i2cPort->requestFrom(_address, nbytes); // Read bytes from slave register address + while (_i2cPort->available()) { + data[i++] = _i2cPort->read(); + } +} + +void TouchClass::clearFlags(void) { + uint8_t buf[3] = {0xD0, 0X00, 0XAB}; + _i2cPort->beginTransmission(_address); + _i2cPort->write(buf, 3); + _i2cPort->endTransmission(); +} + +bool TouchClass::begin(TwoWire &port, uint8_t addr) { + _i2cPort = &port; + _address = addr; + _i2cPort->beginTransmission(_address); + if (0 == _i2cPort->endTransmission()) { + // wakeup(); + return true; + } + return false; +} + +uint8_t TouchClass::scanPoint() { + uint8_t point = 0; + uint8_t buffer[40] = {0}; + uint32_t sumL = 0, sumH = 0; + + buffer[0] = 0xD0; + buffer[1] = 0x00; + readBytes(buffer, 7); + + if (buffer[0] == 0xAB) { + clearFlags(); + return 0; + } + + point = buffer[5] & 0xF; + + if (point == 1) { + buffer[5] = 0xD0; + buffer[6] = 0x07; + readBytes( &buffer[5], 2); + sumL = buffer[5] << 8 | buffer [6]; + + } else if (point > 1) { + buffer[5] = 0xD0; + buffer[6] = 0x07; + readBytes( &buffer[5], 5 * (point - 1) + 3); + sumL = buffer[5 * point + 1] << 8 | buffer[5 * point + 2]; + } + clearFlags(); + + for (int i = 0 ; i < 5 * point; ++i) { + sumH += buffer[i]; + } + + if (sumH != sumL) { + point = 0; + } + if (point) { + uint8_t offset; + for (int i = 0; i < point; ++i) { + if (i == 0) { + offset = 0; + } else { + offset = 4; + } + data[i].id = (buffer[i * 5 + offset] >> 4) & 0x0F; + data[i].state = buffer[i * 5 + offset] & 0x0F; + if (data[i].state == 0x06) { + data[i].state = 0x07; + } else { + data[i].state = 0x06; + } + data[i].y = (uint16_t)((buffer[i * 5 + 1 + offset] << 4) | ((buffer[i * 5 + 3 + offset] >> 4) & 0x0F)); + data[i].x = (uint16_t)((buffer[i * 5 + 2 + offset] << 4) | (buffer[i * 5 + 3 + offset] & 0x0F)); + } + } else { + point = 1; + data[0].id = (buffer[0] >> 4) & 0x0F; + data[0].state = 0x06; + data[0].y = (uint16_t)((buffer[0 * 5 + 1] << 4) | ((buffer[0 * 5 + 3] >> 4) & 0x0F)); + data[0].x = (uint16_t)((buffer[0 * 5 + 2] << 4) | (buffer[0 * 5 + 3] & 0x0F)); + } + // Serial.printf("X:%d Y:%d\n", data[0].x, data[0].y); + return point; +} + +void TouchClass::getPoint(int16_t &x, int16_t &y, uint8_t index) { + if (index >= 4)return; + x = data[index].x; + y = data[index].y; +} + +//if (touch.scanPoint()) { + // touch.getPoint(x, y, 0); + +#define EPD47_address 0x5A + +TouchClass *EPD47_touchp; + +void EPD47_Touch_Init(void) { +FT5206_found = false; +EPD47_touchp = new TouchClass(); + if (EPD47_touchp->begin(Wire, EPD47_address)) { + I2cSetActiveFound(EPD47_address, "EPD47"); + FT5206_found = true; + } +} + +uint8_t EPD47_ctouch_counter = 0; +// no rotation support +void EPD47_RotConvert(int16_t *x, int16_t *y) { +int16_t temp; + if (renderer) { + uint8_t rot=renderer->getRotation(); + switch (rot) { + case 0: + break; + case 1: + temp=*y; + *y=renderer->height()-*x; + *x=temp; + break; + case 2: + *x=renderer->width()-*x; + *y=renderer->height()-*y; + break; + case 3: + temp=*y; + *y=*x; + *x=renderer->width()-temp; + break; + } + } +} + +// check digitizer hit +void EPD47_CheckTouch(void) { + EPD47_ctouch_counter++; + if (2 == EPD47_ctouch_counter) { + // every 100 ms should be enough + EPD47_ctouch_counter = 0; + touched = EPD47_touchp->scanPoint(); + if (touched) { + EPD47_touchp->getPoint(touch_xp, touch_yp, 0); + EPD47_RotConvert(&touch_xp, &touch_yp); + } + //Touch_Check(EPD47_RotConvert); + } +} +#endif // USE_TOUCH_BUTTONS + + + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -91,6 +288,13 @@ bool Xdsp16(uint8_t function) case FUNC_DISPLAY_MODEL: result = true; break; +#ifdef USE_TOUCH_BUTTONS + case FUNC_DISPLAY_EVERY_50_MSECOND: + if (FT5206_found) { + EPD47_CheckTouch(); + } + break; +#endif // USE_TOUCH_BUTTONS } } return result;