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 fb223680b..e09ab71a8 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 @@ -633,6 +633,12 @@ LVGL_PARAMS *Renderer::lvgl_pars(void) { return &lvgl_param; } +void Renderer::ep_update_mode(uint8_t mode) { +} + +void Renderer::ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode) { +} + // #ifndef USE_DISPLAY_LVGL_ONLY @@ -642,6 +648,18 @@ void VButton::xdrawButton(bool inverted) { wr_redir=0; } +void VButton::xinitButtonUL(Renderer *renderer, int16_t gxp, int16_t gyp, uint16_t gxs, uint16_t gys, uint16_t outline,\ + uint16_t fill, uint16_t textcolor , char *label, uint8_t textsize) { + + initButtonUL(renderer, gxp, gyp, gxs, gys, outline, fill, textcolor, label, textsize); + + spars.xp = gxp; + spars.yp = gyp; + spars.xs = gxs; + spars.ys = gys; + +} + boolean VButton::didhit(int16_t x, int16_t y) { return ((x >= spars.xp) && (x < (int16_t) (spars.xp + spars.xs)) && (y >= spars.yp) && (y < (int16_t) (spars.yp + spars.ys))); 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 49f4d7b5e..3e3304fbb 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 @@ -88,6 +88,8 @@ public: virtual void Splash(void); virtual char *devname(void); virtual LVGL_PARAMS *lvgl_pars(void); + virtual void ep_update_mode(uint8_t mode); + virtual void ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode); void setDrawMode(uint8_t mode); uint8_t drawmode; @@ -144,6 +146,8 @@ class VButton : public Adafruit_GFX_Button { boolean didhit(int16_t x, int16_t y); 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); + void xinitButtonUL(Renderer *renderer, int16_t gxp, int16_t gyp, uint16_t gxs, uint16_t gys, uint16_t outline,\ + uint16_t fill, uint16_t textcolor , char *label, uint8_t textsize); }; // #endif // USE_DISPLAY_LVGL_ONLY diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index aa2dae903..6f48d5796 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -343,6 +343,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { Serial.printf("SPED: %d\n", spi_speed*1000000); Serial.printf("Pixels: %d\n", col_mode); Serial.printf("SaMode: %d\n", sa_mode); + Serial.printf("DMA-Mode: %d\n", lvgl_param.use_dma); Serial.printf("opts: %02x,%02x,%02x\n", saw_3, dim_op, startline); diff --git a/lib/lib_display/UDisplay/uDisplay.h b/lib/lib_display/UDisplay/uDisplay.h index 8ce012bf5..3dbc5aed7 100755 --- a/lib/lib_display/UDisplay/uDisplay.h +++ b/lib/lib_display/UDisplay/uDisplay.h @@ -68,10 +68,12 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR }; #define SPI_BEGIN_TRANSACTION if (spi_nr <= 2) beginTransaction(spiSettings); #define SPI_END_TRANSACTION if (spi_nr <= 2) endTransaction(); -#define SPI_CS_LOW if (spi_cs >= 0) GPIO_CLR(spi_cs); -#define SPI_CS_HIGH if (spi_cs >= 0) GPIO_SET(spi_cs); -#define SPI_DC_LOW if (spi_dc >= 0) GPIO_CLR(spi_dc); -#define SPI_DC_HIGH if (spi_dc >= 0) GPIO_SET(spi_dc); + +#define SPI_CS_LOW if (spi_cs >= 0) GPIO_CLR_SLOW(spi_cs); +#define SPI_CS_HIGH if (spi_cs >= 0) GPIO_SET_SLOW(spi_cs); +#define SPI_DC_LOW if (spi_dc >= 0) GPIO_CLR_SLOW(spi_dc); +#define SPI_DC_HIGH if (spi_dc >= 0) GPIO_SET_SLOW(spi_dc); + #define ESP32_PWM_CHANNEL 1 diff --git a/tasmota/homekit.c b/tasmota/homekit.c index 92e19543c..55d71c239 100755 --- a/tasmota/homekit.c +++ b/tasmota/homekit.c @@ -38,7 +38,7 @@ #include #include #include - +#include #include @@ -703,9 +703,9 @@ nextline: #define HK_PASSCODE "111-11-111" int hap_loop_stop(void); +int32_t homekit_pars(uint32_t sel); - -void homekit_main(char *desc, uint32_t flag ) { +int32_t homekit_main(char *desc, uint32_t flag ) { if (desc) { char *cp = desc; cp += 2; @@ -724,7 +724,7 @@ void homekit_main(char *desc, uint32_t flag ) { } if (*cp != '\n') { printf("init error\n"); - return; + return -1; } cp++; hk_desc = cp; @@ -736,17 +736,44 @@ void homekit_main(char *desc, uint32_t flag ) { hap_loop_stop(); // is just the folder in wrapper hap_platfrom_keystore_erase_partition(hap_platform_keystore_get_nvs_partition_name()); + } else if (flag < 3) { + return homekit_pars(flag); } else { hap_loop_stop(); } - return; + + return 0; } - if (!hk_desc) return; + if (!hk_desc) return -2; /* Create the application thread */ xTaskCreate(smart_outlet_thread_entry, SMART_OUTLET_TASK_NAME, SMART_OUTLET_TASK_STACKSIZE, NULL, SMART_OUTLET_TASK_PRIORITY, NULL); + return 0; +} + +#include + +int32_t homekit_pars(uint32_t sel) { + + if (sel == 0) { + // return CONFIG_LWIP_MAX_SOCKETS; + return MEMP_NUM_NETCONN; + } else if (sel == 1) { + return LWIP_SOCKET_OFFSET; + } else { + struct sockaddr name; + socklen_t len = sizeof(name); + uint8_t open_socs = 0; + for (uint32_t cnt = 0; cnt < CONFIG_LWIP_MAX_SOCKETS; cnt++) { + //if (!getsockname(cnt, &name, &len)) { + if (!getpeername(LWIP_SOCKET_OFFSET + cnt, &name, &len)) { + open_socs++; + } + } + return open_socs; + } } #endif // ESP32 diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index d4b4d1134..48fe3e891 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -205,11 +205,17 @@ void alt_eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf) { #endif // LITTLEFS_SCRIPT_SIZE +#include #ifdef TESLA_POWERWALL #include "powerwall.h" #endif +#ifdef USE_DISPLAY_DUMP +#include +extern Renderer *renderer; +#endif + // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution #ifndef EPOCH_OFFSET #define EPOCH_OFFSET 1546300800 @@ -231,7 +237,7 @@ extern FS *ufsp; #endif // USE_UFILESYS -extern "C" void homekit_main(char *, uint32_t); +extern "C" int32_t homekit_main(char *, uint32_t); #ifdef SUPPORT_MQTT_EVENT #include // Import LinkedList library @@ -434,6 +440,9 @@ struct SCRIPT_MEM { bool homekit_running = false; #endif // USE_HOMEKIT uint32_t epoch_offset = EPOCH_OFFSET; +#ifdef USE_SCRIPT_SERIAL + TasmotaSerial *sp; +#endif } glob_script_mem; @@ -3176,6 +3185,143 @@ chknext: goto exit; } #endif //USE_SML_M + +#ifdef USE_SCRIPT_SERIAL + if (!strncmp(vname, "so(", 3)) { + float rxpin, txpin, br; + lp = GetNumericArgument(lp + 3, OPER_EQU, &rxpin, gv); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &txpin, gv); + SCRIPT_SKIP_SPACES + lp = GetNumericArgument(lp, OPER_EQU, &br, gv); + SCRIPT_SKIP_SPACES + uint32_t sconfig = TS_SERIAL_8N1; + if (*lp!=')') { + // serial options, must be 3 chars 8N1, 7E2 etc + uint8_t bits = *lp++ & 0xf; + uint8_t parity = 0; + if (*lp == 'E') parity = 1; + if (*lp == 'O') parity = 2; + lp++; + uint8_t stopb = (*lp++ & 0x3) - 1; + sconfig = (bits - 5) + (parity * 8) + stopb * 4; + } + fvar= -1; + if (glob_script_mem.sp) { + fvar == -1; + } else { + if (Is_gpio_used(rxpin) || Is_gpio_used(txpin)) { + AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used")); + } + + glob_script_mem.sp = new TasmotaSerial(rxpin, txpin, 1); + if (glob_script_mem.sp) { + uint32_t config; +#ifdef ESP8266 + config = pgm_read_byte(kTasmotaSerialConfig + sconfig); +#endif // ESP8266 + +#ifdef ESP32 + config = pgm_read_dword(kTasmotaSerialConfig + sconfig); +#endif // ESP32 + fvar = glob_script_mem.sp->begin(br, config); + uint32_t savc = Settings->serial_config; + Settings->serial_config = sconfig; + AddLog(LOG_LEVEL_INFO, PSTR("Serial port set to %s %d bit/s at rx=%d tx=%d"), GetSerialConfig().c_str(), (uint32_t)br, (uint32_t)rxpin, (uint32_t)txpin); + Settings->serial_config = savc; + if (rxpin == 3 and txpin == 1) ClaimSerial(); + + } else { + fvar = -2; + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sw(", 3)) { + char str[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp + 3, OPER_EQU, str, 0); + fvar = -1; + if (glob_script_mem.sp) { + glob_script_mem.sp->write(str, strlen(str)); + fvar = 0; + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "swb(", 4)) { + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0); + fvar = -1; + if (glob_script_mem.sp) { + glob_script_mem.sp->write((uint8_t)fvar); + fvar = 0; + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sa(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "srb(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + if (fvar > 0) { + fvar = glob_script_mem.sp->read(); + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sp(", 3)) { + fvar = -1; + if (glob_script_mem.sp) { + fvar = glob_script_mem.sp->available(); + if (fvar > 0) { + fvar = glob_script_mem.sp->peek(); + } + } + lp++; + len = 0; + goto exit; + } + if (!strncmp(vname, "sr(", 4)) { + char str[SCRIPT_MAXSSIZE]; + memset(str, 0, sizeof(str)); + fvar = -1; + if (glob_script_mem.sp) { + for (uint8_t index = 0; index < sizeof(str) - 1; index++) { + if (!glob_script_mem.sp->available()) { + break; + } + str[index] = glob_script_mem.sp->read(); + } + } + lp++; + len = 0; + if (sp) strlcpy(sp, str, glob_script_mem.max_ssize); + goto strexit;; + } + if (!strncmp(vname, "sc(", 3)) { + fvar = -1; + if (Script_Close_Serial()) { + fvar = 0; + } + lp+=4; + len = 0; + goto exit; + } +#endif //USE_SCRIPT_SERIAL break; case 't': if (!strncmp(vname, "time", 4)) { @@ -3280,6 +3426,21 @@ chknext: goto exit; } #endif + +#ifdef USE_TIMERS + if (!strncmp(vname, "ttget(", 6)) { + lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + uint8_t index = fvar; + if (index < 1 || index > MAX_TIMERS) index = 1; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); + SCRIPT_SKIP_SPACES + fvar = get_tpars(index - 1, fvar); + lp++; + len = 0; + goto exit; + } +#endif break; case 'u': if (!strncmp(vname, "uptime", 6)) { @@ -3382,7 +3543,7 @@ chknext: goto exit; } #endif // USE_TTGO_WATCH -#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) +#if defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_M5EPD47) if (!strncmp(vname, "wtch(", 5)) { lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, gv); fvar = Touch_Status(fvar); @@ -4498,6 +4659,9 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { // set pin mode lp = GetNumericArgument(lp + 6, OPER_EQU, &fvar, 0); int8_t pinnr = fvar; + if (Is_gpio_used(pinnr)) { + AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used")); + } SCRIPT_SKIP_SPACES uint8_t mode = 0; if ((*lp=='I') || (*lp=='O') || (*lp=='P')) { @@ -5000,6 +5164,25 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { return -1; } +#ifdef USE_SCRIPT_SERIAL +bool Script_Close_Serial() { + if (glob_script_mem.sp) { + glob_script_mem.sp->flush(); + delay(100); + delete(glob_script_mem.sp); + glob_script_mem.sp = 0; + return true; + } + return false; +} +#endif //USE_SCRIPT_SERIAL + +bool Is_gpio_used(uint8_t gpiopin) { + if ((gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { + return true; + } + return false; +} void ScripterEvery100ms(void) { static uint8_t xsns_index = 0; @@ -5440,6 +5623,8 @@ void ScriptSaveSettings(void) { SaveScript(); + } else { + AddLog(LOG_LEVEL_INFO, PSTR("script memory error")); } SaveScriptEnd(); @@ -5481,6 +5666,10 @@ void SaveScriptEnd(void) { return; } +#ifdef USE_SCRIPT_SERIAL + Script_Close_Serial(); +#endif + Run_Scripter(">B\n", 3, 0); Run_Scripter(">BS", 3, 0); @@ -6529,9 +6718,8 @@ char buff[512]; if (sflg) { #ifdef USE_DISPLAY_DUMP - -#include -extern Renderer *renderer; +//#include +//extern Renderer *renderer; // screen copy #define fileHeaderSize 14 @@ -6541,7 +6729,9 @@ extern Renderer *renderer; 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 dmflg = 0; + if (renderer->disp_bpp & 0x40) dmflg = 1; + int8_t bpp = renderer->disp_bpp & 0xbf;; uint8_t *lbp; uint8_t fileHeader[fileHeaderSize]; createBitmapFileHeader(Settings->display_height , Settings->display_width , fileHeader); @@ -6549,8 +6739,7 @@ extern Renderer *renderer; uint8_t infoHeader[infoHeaderSize]; createBitmapInfoHeader(Settings->display_height, Settings->display_width, infoHeader ); Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize); - - if (bpp == -1) { + if (bpp < 0) { for (uint32_t lins = Settings->display_height - 1; lins >= 0 ; lins--) { lbp = lbuf; for (uint32_t cols = 0; cols < Settings->display_width; cols ++) { @@ -6570,16 +6759,30 @@ extern Renderer *renderer; if (bpp == 4) { for (uint32_t cols = 0; cols < Settings->display_width; cols += 2) { uint8_t pixel; - for (uint32_t cnt = 0; cnt <= 1; cnt++) { - if (cnt & 1) { - pixel = *bp >> 4; - } else { - pixel = *bp & 0xf; + if (!dmflg) { + for (uint32_t cnt = 0; cnt <= 1; cnt++) { + if (cnt & 1) { + pixel = *bp >> 4; + } else { + pixel = *bp & 0xf; + } } pixel *= 15; *--lbp = pixel; *--lbp = pixel; *--lbp = pixel; + } else { + for (uint32_t cnt = 0; cnt <= 1; cnt++) { + if (!(cnt & 1)) { + pixel = *bp >> 4; + } else { + pixel = *bp & 0xf; + } + pixel *= 15; + *--lbp = pixel; + *--lbp = pixel; + *--lbp = pixel; + } } bp++; } @@ -6601,8 +6804,8 @@ extern Renderer *renderer; bp++; } } + Webserver->client().write((const char*)lbuf, Settings->display_width * 3); } - Webserver->client().write((const char*)lbuf, Settings->display_width * 3); } if (lbuf) free(lbuf); Webserver->client().stop(); @@ -6796,6 +6999,13 @@ const char SCRIPT_MSG_SLIDER[] PROGMEM = const char SCRIPT_MSG_CHKBOX[] PROGMEM = "
"; +const char SCRIPT_MSG_PULLDOWNa[] PROGMEM = + "
"; + const char SCRIPT_MSG_TEXTINP[] PROGMEM = "
"; @@ -7098,7 +7308,43 @@ void ScriptWebShow(char mc) { uval = 1; } WSContentSend_PD(SCRIPT_MSG_CHKBOX, label, (char*)cp, uval, vname); + } else if (!strncmp(lin, "pd(", 3)) { + // pull down + char *lp = lin + 3; + char *slp = lp; + float val; + lp = GetNumericArgument(lp, OPER_EQU, &val, 0); + SCRIPT_SKIP_SPACES + char vname[16]; + ScriptGetVarname(vname, slp, sizeof(vname)); + + SCRIPT_SKIP_SPACES + char pulabel[SCRIPT_MAXSSIZE]; + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + + WSContentSend_PD(SCRIPT_MSG_PULLDOWNa, vname, pulabel, 1, vname, vname); + + // get pu labels + uint8_t index = 1; + while (*lp) { + SCRIPT_SKIP_SPACES + lp = GetStringArgument(lp, OPER_EQU, pulabel, 0); + char *cp; + if (val == index) { + cp = (char*)"selected"; + } else { + cp = (char*)""; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNb, cp, index, pulabel); + SCRIPT_SKIP_SPACES + if (*lp == ')') { + lp++; + break; + } + index++; + } + WSContentSend_PD(SCRIPT_MSG_PULLDOWNc); } else if (!strncmp(lin, "bu(", 3)) { char *lp = lin + 3; uint8_t bcnt = 0; @@ -8295,6 +8541,42 @@ void lvgl_setup(void) { #endif // USE_LVGL + +#ifdef USE_TIMERS +int32_t get_tpars(uint32_t index, uint32_t sel) { +int32_t retval = 0; + switch (sel) { + case 0: + retval = Settings->timer[index].time; + break; + case 1: + //retval = Settings->timer[index].window; + retval = timer_window[index]; + break; + case 2: + retval = Settings->timer[index].repeat; + break; + case 3: + retval = Settings->timer[index].days; + break; + case 4: + retval = Settings->timer[index].device; + break; + case 5: + retval = Settings->timer[index].power; + break; + case 6: + retval = Settings->timer[index].mode; + break; + case 7: + retval = Settings->timer[index].arm; + break; + } + return retval; +} + +#endif + /*********************************************************************************************\ * Interface \*********************************************************************************************/ diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index bcf545bc5..636d0e1ce 100755 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -701,6 +701,12 @@ void DisplayText(void) if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); //else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); break; + case 'm': + // epaper draw mode currently only for 4,7 inch displays + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->ep_update_mode(temp); + break; case 'r': // rectangle var = atoiv(cp, &temp); @@ -723,7 +729,27 @@ void DisplayText(void) break; case 'u': // rounded rectangle - { int16_t rad; + { int16_t rad, xp, yp, width, height; + if (*cp == 'p') { + // update epaper display + cp++; + var = atoiv(cp, &xp); + cp += var; + cp++; + var = atoiv(cp, &yp); + cp += var; + cp++; + var = atoiv(cp, &width); + cp += var; + cp++; + var = atoiv(cp, &height); + cp += var; + cp++; + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->ep_update_area(xp, yp, width, height, temp); + break; + } var = atoiv(cp, &temp); cp += var; cp++; @@ -1100,7 +1126,7 @@ extern FS *ffsp; if (buttons[num]) { if (!sbt) { buttons[num]->vpower.slider = 0; - buttons[num]->initButtonUL(renderer, gxp, gyp, gxs, gys, GetColorFromIndex(outline),\ + buttons[num]->xinitButtonUL(renderer, gxp, gyp, gxs, gys, GetColorFromIndex(outline),\ GetColorFromIndex(fill), GetColorFromIndex(textcolor), bbuff, textsize); if (!bflags) { // power button @@ -1969,6 +1995,7 @@ void ApplyDisplayDimmer(void) { // still call Berry virtual display in case it is not managed entirely by renderer Xdsp18(FUNC_DISPLAY_DIM); #endif // USE_BERRY + } else { XdspCall(FUNC_DISPLAY_DIM); } @@ -2631,7 +2658,11 @@ void Restore_graph(uint8_t num, char *path) { if (count<=4) { if (count==0) gp->xcnt=atoi(vbuff); } else { - gp->values[count-5]=atoi(vbuff); + uint8_t yval = atoi(vbuff); + if (yval >= gp->ys) { + yval = gp->ys - 1; + } + gp->values[count-5] = yval; } } fp.close(); @@ -2735,9 +2766,9 @@ void AddValue(uint8_t num,float fval) { // decimation option if (gp->decimation<0) { if (gp->dcnt>=-gp->decimation) { - gp->dcnt=0; // calc average - val=gp->summ/-gp->decimation; + val=gp->summ/gp->dcnt; + gp->dcnt=0; gp->summ=0; // add to graph AddGraph(num,val);