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 4146826ab..edb2fb4d5 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 @@ -27,11 +27,7 @@ #include #include "renderer.h" -#define USE_EPD_FONTS -//#define USE_ALL_EPD_FONTS -//#define USE_GFX_FONTS -#define USE_TINY_FONT -#define USE_7SEG_FONT + uint8_t wr_redir=0; @@ -43,8 +39,12 @@ uint8_t wr_redir=0; #define OLED_FONT_HEIGTH 8 #define BLACK 0 -Renderer::Renderer(int16_t x, int16_t y) : -Adafruit_GFX(x, y) { +#ifdef USE_GFX +Renderer::Renderer(int16_t x, int16_t y) : Adafruit_GFX(x, y) { +#else +Renderer::Renderer(int16_t x, int16_t y) { +#endif + font=0; #ifdef USE_EPD_FONTS selected_font = &Font12; @@ -628,6 +628,9 @@ LVGL_PARAMS *Renderer::lvgl_pars(void) { return &lvgl_param; } + +#ifndef LVGL_RENDERER + void VButton::xdrawButton(bool inverted) { wr_redir=1; drawButton(inverted); @@ -723,7 +726,7 @@ uint16_t VButton::UpdateSlider(int16_t x, int16_t y) { } } - +#endif // LVGL_RENDERER 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 f94b65393..e9597a437 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 @@ -9,8 +9,20 @@ #define WHITE 1 #define INVERSE 2 +#define USE_EPD_FONTS +//#define USE_ALL_EPD_FONTS +//#define USE_GFX_FONTS +#define USE_TINY_FONT +#define USE_7SEG_FONT + #define MAX_INDEXCOLORS 32 +//#define LVGL_RENDERER + +#ifdef LVGL_RENDERER +#undef USE_EPD_FONTS +#endif + // depends on GFX driver // GFX patched // a. in class GFX setCursor,setTextSize => virtual @@ -36,7 +48,14 @@ typedef struct LVGL_PARAMS { typedef void (*pwr_cb)(uint8_t); typedef void (*dim_cb)(uint8_t); +#define USE_GFX + +#ifdef USE_GFX class Renderer : public Adafruit_GFX { +#else +class Renderer { +#endif + //Paint(unsigned char* image, int width, int height); //~Renderer(); public: @@ -115,6 +134,7 @@ struct Slider { uint16_t barcol; }; +#ifndef LVGL_RENDERER class VButton : public Adafruit_GFX_Button { public: TButton_State vpower; @@ -125,6 +145,7 @@ class VButton : public Adafruit_GFX_Button { uint16_t UpdateSlider(int16_t x, int16_t y); void SliderInit(Renderer *rend, uint16_t xp, uint16_t yp, uint16_t xs, uint16_t ys, uint16_t nelem, uint16_t bgcol, uint16_t frcol, uint16_t barcol); }; +#endif // LVGL_RENDERER #endif diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index c252395df..de9dcc628 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -20,7 +20,7 @@ #include #include "uDisplay.h" -#define UDSP_DEBUG +//#define UDSP_DEBUG 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,\ diff --git a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp index d9d53bf13..74d28af2e 100644 --- a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp +++ b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.cpp @@ -951,14 +951,13 @@ void RA8876::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) { //RA8876_CS_LOW while (len--) { - uint16_t color=*data++; + uint16_t color = *data++; #if 0 SPI.transfer(RA8876_DATA_WRITE); SPI.transfer(color&0xff); SPI.transfer(RA8876_DATA_WRITE); SPI.transfer(color>>8); - #else //waitWriteFifo(); @@ -1467,3 +1466,128 @@ void RA8876::FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str) setTextColor(tcolor,textbgcolor); xwrite((uint8_t*)str,strlen(str)); } + +// ESP 32 DMA section , derived from TFT_eSPI +#ifdef ESP32 + +/*************************************************************************************** +** Function name: initDMA +** Description: Initialise the DMA engine - returns true if init OK +***************************************************************************************/ +bool RA8876::initDMA() +{ + if (DMA_Enabled) return false; + + esp_err_t ret; + spi_bus_config_t buscfg = { + .mosi_io_num = _mosi, + .miso_io_num = _miso, + .sclk_io_num = _sclk, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = width() * height() * 2 + 8, // TFT screen size + .flags = 0, + .intr_flags = 0 + }; + + + spi_device_interface_config_t devcfg = { + .command_bits = 0, + .address_bits = 0, + .dummy_bits = 0, + .mode = SPI_MODE3, + .duty_cycle_pos = 0, + .cs_ena_pretrans = 0, + .cs_ena_posttrans = 0, + .clock_speed_hz = RA8876_SPI_SPEED, + .input_delay_ns = 0, + .spics_io_num = m_csPin, + .flags = SPI_DEVICE_NO_DUMMY, //0, + .queue_size = 1, + .pre_cb = 0, //dc_callback, //Callback to handle D/C line + .post_cb = 0 + }; + ret = spi_bus_initialize(spi_host, &buscfg, 1); + ESP_ERROR_CHECK(ret); + ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL); + ESP_ERROR_CHECK(ret); + + DMA_Enabled = true; + spiBusyCheck = 0; + return true; +} + +/*************************************************************************************** +** Function name: deInitDMA +** Description: Disconnect the DMA engine from SPI +***************************************************************************************/ +void RA8876::deInitDMA(void) { + if (!DMA_Enabled) return; + spi_bus_remove_device(dmaHAL); + spi_bus_free(spi_host); + DMA_Enabled = false; +} + +/*************************************************************************************** +** Function name: dmaBusy +** Description: Check if DMA is busy +***************************************************************************************/ +bool RA8876::dmaBusy(void) { + if (!DMA_Enabled || !spiBusyCheck) return false; + + spi_transaction_t *rtrans; + esp_err_t ret; + uint8_t checks = spiBusyCheck; + for (int i = 0; i < checks; ++i) { + ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0); + if (ret == ESP_OK) spiBusyCheck--; + } + + //Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck); + if (spiBusyCheck == 0) return false; + return true; +} + + +/*************************************************************************************** +** Function name: dmaWait +** Description: Wait until DMA is over (blocking!) +***************************************************************************************/ +void RA8876::dmaWait(void) { + if (!DMA_Enabled || !spiBusyCheck) return; + spi_transaction_t *rtrans; + esp_err_t ret; + for (int i = 0; i < spiBusyCheck; ++i) { + ret = spi_device_get_trans_result(dmaHAL, &rtrans, portMAX_DELAY); + assert(ret == ESP_OK); + } + spiBusyCheck = 0; +} + + +/*************************************************************************************** +** Function name: pushPixelsDMA +** Description: Push pixels to TFT (len must be less than 32767) +***************************************************************************************/ +// This will byte swap the original image if setSwapBytes(true) was called by sketch. +void RA8876::pushPixelsDMA(uint16_t* image, uint32_t len) { + + if ((len == 0) || (!DMA_Enabled)) return; + + dmaWait(); + + esp_err_t ret; + + memset(&trans, 0, sizeof(spi_transaction_t)); + + trans.user = (void *)1; + trans.tx_buffer = image; //finally send the line data + trans.length = len * 16; //Data length, in bits + trans.flags = 0; //SPI_TRANS_USE_TXDATA flag + + ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY); + assert(ret == ESP_OK); + + spiBusyCheck++; +} +#endif // ESP32 diff --git a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h index 14b821471..7cf2f031b 100644 --- a/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h +++ b/lib/lib_display/Xlatb_RA8876-gemu-1.0/RA8876.h @@ -22,6 +22,9 @@ #include "Arduino.h" #include #include +#ifdef ESP32 +#include "driver/spi_master.h" +#endif #undef SPRINT #define SPRINT(A) {char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);} @@ -147,7 +150,7 @@ typedef uint8_t FontFlags; // 1MHz. TODO: Figure out actual speed to use // Data sheet section 5.2 says maximum SPI clock is 50MHz. //#define RA8876_SPI_SPEED 10000000 -#define RA8876_SPI_SPEED 20000000 +#define RA8876_SPI_SPEED 25000000 // With SPI, the RA8876 expects an initial byte where the top two bits are meaningful. Bit 7 // is A0, bit 6 is WR#. See data sheet section 7.3.2 and section 19. @@ -565,6 +568,21 @@ class RA8876 : public Renderer { enum FontSource m_fontSource; enum FontSize m_fontSize; FontFlags m_fontFlags; + +#ifdef ESP32 + // dma section + bool DMA_Enabled = false; + uint8_t spiBusyCheck = 0; + spi_transaction_t trans; + spi_device_handle_t dmaHAL; + spi_host_device_t spi_host = VSPI_HOST; + // spi_host_device_t spi_host = VSPI_HOST; + bool initDMA(); + void deInitDMA(void); + bool dmaBusy(void); + void dmaWait(void); + void pushPixelsDMA(uint16_t* image, uint32_t len); +#endif // ESP32 }; #endif diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index ef6e3429b..3f5cb8e73 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -2668,7 +2668,8 @@ chknext: #ifdef USE_LVGL if (!strncmp(vname, "lvgl(", 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); - fvar = lvgl_test(fvar); + SCRIPT_SKIP_SPACES + fvar = lvgl_test(&lp, fvar); lp++; len = 0; goto exit; @@ -7870,82 +7871,192 @@ uint32_t script_i2c(uint8_t sel, uint8_t val, uint8_t val1) { #include #include "lvgl.h" - -const char ili9342[] PROGMEM = -":H,ILI9342,320,240,16,SPI,1,*,*,*,*,*,*,*,40\n" -":S,2,1,3,0,100,100\n" -":I\n" -"EF,3,03,80,02\n" -"CF,3,00,C1,30\n" -"ED,4,64,03,12,81\n" -"E8,3,85,00,78\n" -"CB,5,39,2C,00,34,02\n" -"F7,1,20\n" -"EA,2,00,00\n" -"C0,1,23\n" -"C1,1,10\n" -"C5,2,3e,28\n" -"C7,1,86\n" -"36,1,48\n" -"37,1,00\n" -"3A,1,55\n" -"B1,2,00,18\n" -"B6,3,08,82,27\n" -"F2,1,00\n" -"26,1,01\n" -"E0,0F,0F,31,2B,0C,0E,08,4E,F1,37,07,10,03,0E,09,00\n" -"E1,0F,00,0E,14,03,11,07,31,C1,48,08,0F,0C,31,36,0F\n" -"21,80\n" -"11,80\n" -"29,80\n" -":o,28\n" -":O,29\n" -":A,2A,2B,2C,16\n" -":R,36\n" -":0,08,00,00,00\n" -":1,A8,00,00,01\n" -":2,C8,00,00,02\n" -":3,68,00,00,03\n" -":i,21,20\n" -":TI2,38,22,21\n" -"#\n"; +#define MAX_LVGL_OBJS 8 +uint8_t lvgl_numobjs; +lv_obj_t *lvgl_buttons[MAX_LVGL_OBJS]; void start_lvgl(const char * uconfig); +lv_event_t lvgl_last_event; +uint8_t lvgl_last_object; +uint8_t lvgl_last_slider; -void btn_event_cb(lv_obj_t * btn, lv_event_t event); -void btn_event_cb(lv_obj_t * btn, lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - AddLog_P(LOG_LEVEL_INFO,PSTR(">>> clicked")); +void lvgl_set_last(lv_obj_t * obj, lv_event_t event); +void lvgl_set_last(lv_obj_t * obj, lv_event_t event) { + lvgl_last_event = event; + lvgl_last_object = 0; + for (uint8_t cnt = 0; cnt < MAX_LVGL_OBJS; cnt++) { + if (lvgl_buttons[cnt] == obj) { + lvgl_last_object = cnt + 1; + return; } + } } -int32_t lvgl_test(int32_t p) { - - start_lvgl(ili9342); - - lv_obj_clean(lv_scr_act()); - - if (p == 0) { - lv_obj_t *label1 = lv_label_create(lv_scr_act(), NULL); - /*Modify the Label's text*/ - lv_label_set_text(label1, "Hello world!"); - /* Align the Label to the center - * NULL means align on parent (which is the screen now) - * 0, 0 at the end means an x, y offset after alignment*/ - lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, 0); - /*Add a button*/ - lv_obj_t *btn1 = lv_btn_create(lv_scr_act(), NULL); /*Add to the active screen*/ - lv_obj_set_pos(btn1, 2, 2); /*Adjust the position*/ - lv_obj_set_size(btn1, 96, 30); /* set size of button */ - lv_obj_set_event_cb(btn1, btn_event_cb); - /*Add text*/ - lv_obj_t *label = lv_label_create(btn1, NULL); /*Put on 'btn1'*/ - lv_label_set_text(label, "Click"); - } else { - lvgl_setup(); +void btn_event_cb(lv_obj_t * btn, lv_event_t event); +void btn_event_cb(lv_obj_t * btn, lv_event_t event) { + lvgl_set_last(btn, event); + if (event == LV_EVENT_CLICKED) { + Run_Scripter(">lvb", 4, 0); } - return 0; +} + +void slider_event_cb(lv_obj_t * sld, lv_event_t event); +void slider_event_cb(lv_obj_t * sld, lv_event_t event) { + lvgl_set_last(sld, event); + lvgl_last_slider = lv_slider_get_value(sld); + if (event == LV_EVENT_VALUE_CHANGED) { + Run_Scripter(">lvs", 4, 0); + } +} + +void lvgl_StoreObj(lv_obj_t *obj); +void lvgl_StoreObj(lv_obj_t *obj) { + if (lvgl_numobjs < MAX_LVGL_OBJS) { + lvgl_buttons[lvgl_numobjs] = obj; + lvgl_numobjs++; + } +} + +int32_t lvgl_test(char **lpp, int32_t p) { + char *lp = *lpp; + lv_obj_t *obj; + lv_obj_t *label; + float xp, yp, xs, ys, min, max; + char str[SCRIPT_MAXSSIZE]; + int32_t res = 0; + + switch (p) { + case 0: + start_lvgl(0); + lvgl_numobjs = 0; + for (uint8_t cnt = 0; cnt < MAX_LVGL_OBJS; cnt++) { + lvgl_buttons[cnt] = 0; + } + break; + + case 1: + lv_obj_clean(lv_scr_act()); + break; + + case 2: + // create button; + lp = GetNumericArgument(lp, OPER_EQU, &xp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &yp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &xs, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &ys, 0); + SCRIPT_SKIP_SPACES + lp = GetStringArgument(lp, OPER_EQU, str, 0); + SCRIPT_SKIP_SPACES + + obj = lv_btn_create(lv_scr_act(), NULL); + lv_obj_set_pos(obj, xp, yp); + lv_obj_set_size(obj, xs, ys); + lv_obj_set_event_cb(obj, btn_event_cb); + label = lv_label_create(obj, NULL); + lv_label_set_text(label, str); + lvgl_StoreObj(obj); + break; + + case 3: + lp = GetNumericArgument(lp, OPER_EQU, &xp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &yp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &xs, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &ys, 0); + SCRIPT_SKIP_SPACES + + obj = lv_slider_create(lv_scr_act(), NULL); + lv_obj_set_pos(obj, xp, yp); + lv_obj_set_size(obj, xs, ys); + lv_obj_set_event_cb(obj, slider_event_cb); + lvgl_StoreObj(obj); + break; + + case 4: + lp = GetNumericArgument(lp, OPER_EQU, &xp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &yp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &xs, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &ys, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &min, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &max, 0); + SCRIPT_SKIP_SPACES + + obj = lv_gauge_create(lv_scr_act(), NULL); + lv_obj_set_pos(obj, xp, yp); + lv_obj_set_size(obj, xs, ys); + lv_gauge_set_range(obj, min, max); + lvgl_StoreObj(obj); + break; + + case 5: + lp = GetNumericArgument(lp, OPER_EQU, &min, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &max, 0); + SCRIPT_SKIP_SPACES + if (lvgl_buttons[(uint8_t)min - 1]) { + lv_gauge_set_value(lvgl_buttons[(uint8_t)min - 1], 0, max); + } + break; + + case 6: + // create label; + lp = GetNumericArgument(lp, OPER_EQU, &xp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &yp, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &xs, 0); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &ys, 0); + SCRIPT_SKIP_SPACES + lp = GetStringArgument(lp, OPER_EQU, str, 0); + SCRIPT_SKIP_SPACES + + obj = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_pos(obj, xp, yp); + lv_obj_set_size(obj, xs, ys); + lv_label_set_text(obj, str); + lvgl_StoreObj(obj); + break; + + case 7: + lp = GetNumericArgument(lp, OPER_EQU, &min, 0); + SCRIPT_SKIP_SPACES + lp = GetStringArgument(lp, OPER_EQU, str, 0); + SCRIPT_SKIP_SPACES + if (lvgl_buttons[(uint8_t)min - 1]) { + lv_label_set_text(lvgl_buttons[(uint8_t)min - 1], str); + } + break; + + case 50: + res = lvgl_last_object; + break; + case 51: + res = lvgl_last_event; + break; + case 52: + res = lvgl_last_slider; + break; + + + default: + lvgl_setup(); + break; + } + + *lpp = lp; + return res; } lv_obj_t *tabview, // LittlevGL tabview object diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index e90eab48a..516bb12b2 100755 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -27,19 +27,12 @@ Renderer *renderer; enum ColorType { COLOR_BW, COLOR_COLOR }; -#ifndef MAX_TOUCH_BUTTONS -#define MAX_TOUCH_BUTTONS 16 -#endif #ifdef USE_UFILESYS extern FS *ufsp; extern FS *ffsp; #endif -#ifdef USE_TOUCH_BUTTONS -VButton *buttons[MAX_TOUCH_BUTTONS]; -#endif - // drawing color is WHITE // on epaper the whole display buffer is transfered inverted this results in white paper uint16_t fg_color = 1; @@ -2673,277 +2666,6 @@ void AddValue(uint8_t num,float fval) { } #endif // USE_GRAPH -/*********************************************************************************************\ - * Touch panel control -\*********************************************************************************************/ - - -bool FT5206_found = false; -bool XPT2046_found = false; -int16_t touch_xp; -int16_t touch_yp; -bool touched; - -uint32_t Touch_Status(uint32_t sel) { - if (FT5206_found || XPT2046_found) { - switch (sel) { - case 0: - return touched; - case 1: - return touch_xp; - case 2: - return touch_yp; - } - return 0; - } else { - return 0; - } -} - -#if defined(USE_FT5206) || defined(USE_XPT2046) - - -#ifdef USE_M5STACK_CORE2 -uint8_t tbstate[3]; -#endif // USE_M5STACK_CORE2 - -#ifdef USE_FT5206 -#include -// touch panel controller -#undef FT5206_address -#define FT5206_address 0x38 - -FT5206_Class *FT5206_touchp; - - -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"); - FT5206_found = true; - } - return FT5206_found; -} - -bool FT5206_touched() { - return FT5206_touchp->touched(); -} -int16_t FT5206_x() { - TP_Point pLoc = FT5206_touchp->getPoint(0); - return pLoc.x; -} -int16_t FT5206_y() { - TP_Point pLoc = FT5206_touchp->getPoint(0); - return pLoc.y; -} -#endif // USE_FT5206 - -#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(); - if (XPT2046_found) { - AddLog(LOG_LEVEL_INFO, PSTR("TS: XPT2046")); - } - return XPT2046_found; -} -bool XPT2046_touched() { - return XPT2046_touchp->touched(); -} -int16_t XPT2046_x() { - TS_Point pLoc = XPT2046_touchp->getPoint(); - return pLoc.x; -} -int16_t XPT2046_y() { - TS_Point pLoc = XPT2046_touchp->getPoint(); - return pLoc.y; -} -#endif // USE_XPT2046 - - - -void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { - -#ifdef USE_FT5206 - if (FT5206_found) { - touch_xp = FT5206_x(); - touch_yp = FT5206_y(); - touched = FT5206_touched(); - } -#endif // USE_FT5206 - -#ifdef USE_XPT2046 - if (XPT2046_found) { - touch_xp = XPT2046_x(); - touch_yp = XPT2046_y(); - touched = XPT2046_touched(); - } -#endif // USE_XPT2046 - - if (touched) { - -#ifdef USE_TOUCH_BUTTONS -#ifdef USE_M5STACK_CORE2 - // handle 3 built in touch buttons - uint16_t xcenter = 80; -#define TDELTA 30 -#define TYPOS 275 - for (uint32_t tbut = 0; tbut < 3; tbut++) { - if (touch_xp > (xcenter - TDELTA) && touch_xp < (xcenter + TDELTA) && touch_yp > (TYPOS - TDELTA) && touch_yp < (TYPOS + TDELTA)) { - // hit a button - if (!(tbstate[tbut] & 1)) { - // pressed - tbstate[tbut] |= 1; - //AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d pressed"), tbut); - Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1); - } - } - xcenter += 100; - } -#endif // USE_M5STACK_CORE2 -#endif // USE_TOUCH_BUTTONS - - rotconvert(&touch_xp, &touch_yp); - -#ifdef USE_TOUCH_BUTTONS - CheckTouchButtons(touched, touch_xp, touch_yp); -#endif // USE_TOUCH_BUTTONS - - } else { -#ifdef USE_M5STACK_CORE2 - for (uint32_t tbut = 0; tbut < 3; tbut++) { - if (tbstate[tbut] & 1) { - // released - tbstate[tbut] &= 0xfe; - Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1); - //AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d released"), tbut); - } - } -#endif // USE_M5STACK_CORE2 - -#ifdef USE_TOUCH_BUTTONS - CheckTouchButtons(touched, touch_xp, touch_yp); -#endif // USE_TOUCH_BUTTONS - - } -} -#endif - -#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); -#endif -#ifdef USE_XPT2046 - if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index+1, val); -#endif // USE_XPT2046 - MqttPublishTeleSensor(); -} - -void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower.on_off = 1; - else buttons[count]->vpower.on_off = 0; -} - - - -void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) { - uint16_t temp; - uint8_t rbutt=0; - uint8_t vbutt=0; - - if (!renderer) return; - if (touched) { - // AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("touch after convert %d - %d"), pLoc.x, pLoc.y); - // now must compare with defined buttons - for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) { - if (buttons[count]) { - if (!buttons[count]->vpower.slider) { - if (!buttons[count]->vpower.disable) { - if (buttons[count]->contains(touch_x, touch_y)) { - // did hit - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!buttons[count]->vpower.is_virtual) { - uint8_t pwr=bitRead(TasmotaGlobal.power, rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - Touch_RDW_BUTT(count, !pwr); - } - } else { - // virtual button - const char *cp; - if (!buttons[count]->vpower.is_pushbutton) { - // toggle button - buttons[count]->vpower.on_off ^= 1; - cp="TBT"; - } else { - // push button - buttons[count]->vpower.on_off = 1; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower.on_off); - Touch_MQTT(count, cp, buttons[count]->vpower.on_off); - } - } - } - if (!buttons[count]->vpower.is_virtual) { - rbutt++; - } else { - vbutt++; - } - } - } else { - // slider - if (buttons[count]->didhit(touch_x, touch_y)) { - uint16_t value = buttons[count]->UpdateSlider(touch_x, touch_y); - Touch_MQTT(count, "SLD", value); - } - } - } - } - - } else { - // no hit - for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) { - if (buttons[count]) { - if (!buttons[count]->vpower.slider) { - buttons[count]->press(false); - if (buttons[count]->justReleased()) { - if (buttons[count]->vpower.is_virtual) { - if (buttons[count]->vpower.is_pushbutton) { - // push button - buttons[count]->vpower.on_off = 0; - Touch_MQTT(count,"PBT", buttons[count]->vpower.on_off); - buttons[count]->xdrawButton(buttons[count]->vpower.on_off); - } - } - } - if (!buttons[count]->vpower.is_virtual) { - // check if power button stage changed - uint8_t pwr = bitRead(TasmotaGlobal.power, rbutt); - uint8_t vpwr = buttons[count]->vpower.on_off; - if (pwr != vpwr) { - Touch_RDW_BUTT(count, pwr); - } - rbutt++; - } - } - } - } - touch_xp = 0; - touch_yp = 0; - } -} -#endif // USE_TOUCH_BUTTONS - - /*********************************************************************************************\ * Interface \*********************************************************************************************/ diff --git a/tasmota/xdrv_55_touch.ino b/tasmota/xdrv_55_touch.ino new file mode 100644 index 000000000..b02944328 --- /dev/null +++ b/tasmota/xdrv_55_touch.ino @@ -0,0 +1,314 @@ +/* + xdrv_55_touch.ino - Touch contolers + + Copyright (C) 2021 Gerhard Mutz and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + + +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) + +#ifdef LVGL_RENDERER +#undef USE_TOUCH_BUTTONS +#endif + +#include + +#define XDRV_55 55 + +bool FT5206_found = false; +bool XPT2046_found = false; +int16_t touch_xp; +int16_t touch_yp; +bool touched; + +#ifndef MAX_TOUCH_BUTTONS +#define MAX_TOUCH_BUTTONS 16 +#endif + +#ifdef USE_TOUCH_BUTTONS +VButton *buttons[MAX_TOUCH_BUTTONS]; +#endif + +uint32_t Touch_Status(uint32_t sel) { + if (FT5206_found || XPT2046_found) { + switch (sel) { + case 0: + return touched; + case 1: + return touch_xp; + case 2: + return touch_yp; + } + return 0; + } else { + return 0; + } +} + +#ifdef USE_M5STACK_CORE2 +uint8_t tbstate[3]; +#endif // USE_M5STACK_CORE2 + +#ifdef USE_FT5206 +#include +// touch panel controller +#undef FT5206_address +#define FT5206_address 0x38 + +FT5206_Class *FT5206_touchp; + +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"); + FT5206_found = true; + } + //AddLog(LOG_LEVEL_INFO, PSTR("TS: FT5206 %d"),FT5206_found); + return FT5206_found; +} + +bool FT5206_touched() { + return FT5206_touchp->touched(); +} +int16_t FT5206_x() { + TP_Point pLoc = FT5206_touchp->getPoint(0); + return pLoc.x; +} +int16_t FT5206_y() { + TP_Point pLoc = FT5206_touchp->getPoint(0); + return pLoc.y; +} +#endif // USE_FT5206 + +#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(); + if (XPT2046_found) { + AddLog(LOG_LEVEL_INFO, PSTR("TS: XPT2046")); + } + return XPT2046_found; +} +bool XPT2046_touched() { + return XPT2046_touchp->touched(); +} +int16_t XPT2046_x() { + TS_Point pLoc = XPT2046_touchp->getPoint(); + return pLoc.x; +} +int16_t XPT2046_y() { + TS_Point pLoc = XPT2046_touchp->getPoint(); + return pLoc.y; +} +#endif // USE_XPT2046 + + + +void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) { + +#ifdef USE_FT5206 + if (FT5206_found) { + touch_xp = FT5206_x(); + touch_yp = FT5206_y(); + touched = FT5206_touched(); + } +#endif // USE_FT5206 + +#ifdef USE_XPT2046 + if (XPT2046_found) { + touch_xp = XPT2046_x(); + touch_yp = XPT2046_y(); + touched = XPT2046_touched(); + } +#endif // USE_XPT2046 + + if (touched) { + +#ifdef USE_TOUCH_BUTTONS +#ifdef USE_M5STACK_CORE2 + // handle 3 built in touch buttons + uint16_t xcenter = 80; +#define TDELTA 30 +#define TYPOS 275 + for (uint32_t tbut = 0; tbut < 3; tbut++) { + if (touch_xp > (xcenter - TDELTA) && touch_xp < (xcenter + TDELTA) && touch_yp > (TYPOS - TDELTA) && touch_yp < (TYPOS + TDELTA)) { + // hit a button + if (!(tbstate[tbut] & 1)) { + // pressed + tbstate[tbut] |= 1; + //AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d pressed"), tbut); + Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1); + } + } + xcenter += 100; + } +#endif // USE_M5STACK_CORE2 +#endif // USE_TOUCH_BUTTONS + + rotconvert(&touch_xp, &touch_yp); + +#ifdef USE_TOUCH_BUTTONS + CheckTouchButtons(touched, touch_xp, touch_yp); +#endif // USE_TOUCH_BUTTONS + + } else { +#ifdef USE_M5STACK_CORE2 + for (uint32_t tbut = 0; tbut < 3; tbut++) { + if (tbstate[tbut] & 1) { + // released + tbstate[tbut] &= 0xfe; + Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1); + //AddLog(LOG_LEVEL_INFO, PSTR("tbut: %d released"), tbut); + } + } +#endif // USE_M5STACK_CORE2 + +#ifdef USE_TOUCH_BUTTONS + CheckTouchButtons(touched, touch_xp, touch_yp); +#endif // USE_TOUCH_BUTTONS + + } +} + +#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); +#endif +#ifdef USE_XPT2046 + if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index+1, val); +#endif // USE_XPT2046 + MqttPublishTeleSensor(); +} + +void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower.on_off = 1; + else buttons[count]->vpower.on_off = 0; +} + +void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) { + uint16_t temp; + uint8_t rbutt=0; + uint8_t vbutt=0; + + if (!renderer) return; + if (touched) { + // AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("touch after convert %d - %d"), pLoc.x, pLoc.y); + // now must compare with defined buttons + for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) { + if (buttons[count]) { + if (!buttons[count]->vpower.slider) { + if (!buttons[count]->vpower.disable) { + if (buttons[count]->contains(touch_x, touch_y)) { + // did hit + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!buttons[count]->vpower.is_virtual) { + uint8_t pwr=bitRead(TasmotaGlobal.power, rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + Touch_RDW_BUTT(count, !pwr); + } + } else { + // virtual button + const char *cp; + if (!buttons[count]->vpower.is_pushbutton) { + // toggle button + buttons[count]->vpower.on_off ^= 1; + cp="TBT"; + } else { + // push button + buttons[count]->vpower.on_off = 1; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower.on_off); + Touch_MQTT(count, cp, buttons[count]->vpower.on_off); + } + } + } + if (!buttons[count]->vpower.is_virtual) { + rbutt++; + } else { + vbutt++; + } + } + } else { + // slider + if (buttons[count]->didhit(touch_x, touch_y)) { + uint16_t value = buttons[count]->UpdateSlider(touch_x, touch_y); + Touch_MQTT(count, "SLD", value); + } + } + } + } + + } else { + // no hit + for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) { + if (buttons[count]) { + if (!buttons[count]->vpower.slider) { + buttons[count]->press(false); + if (buttons[count]->justReleased()) { + if (buttons[count]->vpower.is_virtual) { + if (buttons[count]->vpower.is_pushbutton) { + // push button + buttons[count]->vpower.on_off = 0; + Touch_MQTT(count,"PBT", buttons[count]->vpower.on_off); + buttons[count]->xdrawButton(buttons[count]->vpower.on_off); + } + } + } + if (!buttons[count]->vpower.is_virtual) { + // check if power button stage changed + uint8_t pwr = bitRead(TasmotaGlobal.power, rbutt); + uint8_t vpwr = buttons[count]->vpower.on_off; + if (pwr != vpwr) { + Touch_RDW_BUTT(count, pwr); + } + rbutt++; + } + } + } + } + touch_xp = 0; + touch_yp = 0; + } +} +#endif // USE_TOUCH_BUTTONS + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ +bool Xdrv55(uint8_t function) { + bool result = false; + + switch (function) { + case FUNC_INIT: + break; + case FUNC_EVERY_100_MSECOND: + break; + } + return result; +} + +#endif // USE_TOUCH diff --git a/tasmota/xdsp_04_ili9341.ino b/tasmota/xdsp_04_ili9341.ino index 73d6c183e..32844cab0 100644 --- a/tasmota/xdsp_04_ili9341.ino +++ b/tasmota/xdsp_04_ili9341.ino @@ -40,6 +40,8 @@ uint8_t ili9342_ctouch_counter = 0; bool tft_init_done = false; +void Core2DisplayPower(uint8_t on); +void Core2DisplayDim(uint8_t dim); //Settings.display_options.type = ILIMODE_9341; @@ -89,6 +91,11 @@ void ILI9341_InitDriver() ili9341_2->init(Settings.display_width, Settings.display_height); renderer = ili9341_2; +#ifdef USE_M5STACK_CORE2 + renderer->SetPwrCB(Core2DisplayPower); + renderer->SetDimCB(Core2DisplayDim); +#endif + renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); renderer->dim(Settings.display_dimmer); @@ -131,22 +138,6 @@ void ILI9341_InitDriver() } } - -void Core2DisplayPower(uint8_t on); -void Core2DisplayDim(uint8_t dim); - -void ili9342_bpwr(uint8_t on) { -#ifdef USE_M5STACK_CORE2 - Core2DisplayPower(on); -#endif -} - -void ili9342_dimm(uint8_t dim) { -#ifdef USE_M5STACK_CORE2 - Core2DisplayDim(dim); -#endif -} - #if defined(USE_FT5206) || defined(USE_XPT2046) #ifdef USE_TOUCH_BUTTONS diff --git a/tasmota/xdsp_17_universal.ino b/tasmota/xdsp_17_universal.ino index b91dc9134..588aaa8ba 100644 --- a/tasmota/xdsp_17_universal.ino +++ b/tasmota/xdsp_17_universal.ino @@ -18,7 +18,7 @@ */ -#ifdef USE_DISPLAY +#if defined(USE_DISPLAY) || defined(LVGL_RENDERER) #ifdef USE_UNIVERSAL_DISPLAY #define XDSP_17 17 @@ -27,14 +27,23 @@ bool udisp_init_done = false; uint8_t ctouch_counter; -extern uint8_t color_type; -extern uint16_t fg_color; -extern uint16_t bg_color; + #ifdef USE_UFILESYS extern FS *ffsp; #endif +#ifndef USE_DISPLAY +uint8_t color_type; +uint16_t fg_color; +uint16_t bg_color; +Renderer *renderer; +#else +extern uint8_t color_type; +extern uint16_t fg_color; +extern uint16_t bg_color; +#endif + #define DISPDESC_SIZE 1000 @@ -340,22 +349,6 @@ uDisplay *udisp; /*********************************************************************************************/ -/* - -void udisp_bpwr(uint8_t on) { -#ifdef USE_M5STACK_CORE2 - Core2DisplayPower(on); -#endif -} - -void udisp_dimm(uint8_t dim) { -#ifdef USE_M5STACK_CORE2 - Core2DisplayDim(dim); -#endif -} - -*/ - void TS_RotConvert(int16_t *x, int16_t *y) { if (renderer) renderer->TS_RotConvert(x, y); } @@ -462,8 +455,8 @@ void UDISP_Refresh(void) // Every second * Interface \*********************************************************************************************/ -bool Xdsp17(uint8_t function) -{ +#ifndef LVGL_RENDERER +bool Xdsp17(uint8_t function) { bool result = false; if (FUNC_DISPLAY_INIT_DRIVER == function) { @@ -493,6 +486,7 @@ bool Xdsp17(uint8_t function) } return result; } +#endif // !LVGL_RENDERER #endif // USE_UNIVERSAL_DISPLAY #endif // USE_DISPLAY