diff --git a/esp32_partition_app1984k_spiffs60k.csv b/esp32_partition_app1984k_spiffs60k.csv new file mode 100644 index 000000000..e8bcd9d49 --- /dev/null +++ b/esp32_partition_app1984k_spiffs60k.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1F0000, +app1, app, ota_1, 0x200000, 0x1F0000, +spiffs, data, spiffs, 0x3F0000,0xf000, +eeprom, data, nvs, 0x3FF000,0x1000, diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 050c2e390..b6008abcf 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -399,6 +399,7 @@ #define USE_RULES // Add support for rules (+8k code) #define USE_RULES_COMPRESSION // Compresses rules in Flash at about ~50% (+3.3k code) //#define USE_SCRIPT // Add support for script (+17k code) + #define USE_SCRIPT_COMPRESSION //#define USE_SCRIPT_FATFS 4 // Script: Add FAT FileSystem Support // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) diff --git a/tasmota/support_eeprom.ino b/tasmota/support_eeprom.ino new file mode 100644 index 000000000..b990aa242 --- /dev/null +++ b/tasmota/support_eeprom.ino @@ -0,0 +1,89 @@ +/* + support_eeprom.ino - eeprom support for Sonoff-Tasmota + + Copyright (C) 2020 Theo Arends & Gerhard Mutz + + 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 . + + + supports hardware i2c eeprom 24c256 and flash eeprom simulation on ESP8266 and ESP32 + all ESP8266 linker files contain 4k eeprom partition + ESP32 requires esp32_partition_app1984k_spiffs60k.csv for 4k eeprom +*/ + + +#ifdef USE_EEPROM + +#ifdef USE_24C256 + // i2c eeprom +#include +#define EEPROM_ADDRESS 0x50 +static Eeprom24C128_256 m_eeprom(EEPROM_ADDRESS); + +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + m_eeprom.writeBytes(addr,len,(uint8_t*)buff); +} +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + m_eeprom.readBytes(addr,len,(uint8_t*)buff); +} + +uint32_t eeprom_init(uint32_t size) { + if (i2c_flg) { + if (I2cActive(EEPROM_ADDRESS) || I2cSetDevice(EEPROM_ADDRESS)) { + // eeprom is present + I2cSetActiveFound(EEPROM_ADDRESS, "24C256"); + return 1; + } + } + return 0; +} + +#else // USE_24C256 + +#ifdef ESP32 + +// esp32 uses eeprom section +uint32_t eeprom_init(uint32_t size) { + return EEPROM.begin(size); +} +void eeprom_writeBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + EEPROM.writeBytes(addr, buff, len); + EEPROM.commit(); +} +void eeprom_readBytes(uint32_t addr, uint32_t len, uint8_t *buff) { + EEPROM.readBytes(addr, buff, len); +} + +#else +// esp8266 uses eeprom section +uint32_t eeprom_init(uint32_t size) { + EEPROM.begin(size); + return 1; +} +void eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf) { + for (uint32_t cnt=0; cnt -//Unishox compressor; // singleton #define SCRIPT_COMPRESS compressor.unishox_compress #define SCRIPT_DECOMPRESS compressor.unishox_decompress #ifndef UNISHOXRSIZE @@ -78,17 +119,19 @@ uint32_t DecodeLightId(uint32_t hue_id); #endif #endif // USE_SCRIPT_COMPRESSION -#if (defined(LITTLEFS_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS)) || (USE_SCRIPT_FATFS==-1) +#if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1) #ifdef ESP32 #include "FS.h" #include "SPIFFS.h" #else #include #endif - FS *fsp; +#endif // LITTLEFS_SCRIPT_SIZE + +#ifdef LITTLEFS_SCRIPT_SIZE void SaveFile(const char *name,const uint8_t *buf,uint32_t len) { File file = fsp->open(name, "w"); if (!file) return; @@ -116,7 +159,7 @@ void LoadFile(const char *name,uint8_t *buf,uint32_t len) { file.read(buf, len); file.close(); } -#endif +#endif // LITTLEFS_SCRIPT_SIZE // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution #define EPOCH_OFFSET 1546300800 @@ -317,23 +360,10 @@ void RulesTeleperiod(void) { } // EEPROM MACROS -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS // i2c eeprom -#include -#define EEPROM_ADDRESS 0x50 -// strange bug, crashes with powers of 2 ??? 4096 crashes -#ifndef EEP_SCRIPT_SIZE -#define EEP_SCRIPT_SIZE 4095 -#endif +#define EEP_WRITE(A,B,C) eeprom_writeBytes(A,B,(uint8_t*)C); +#define EEP_READ(A,B,C) eeprom_readBytes(A,B,(uint8_t*)C); -static Eeprom24C128_256 eeprom(EEPROM_ADDRESS); -// eeprom.writeBytes(address, length, buffer); -#define EEP_WRITE(A,B,C) eeprom.writeBytes(A,B,(uint8_t*)C); -// eeprom.readBytes(address, length, buffer); -#define EEP_READ(A,B,C) eeprom.readBytes(A,B,(uint8_t*)C); -#endif -#endif #define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; #define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; @@ -651,13 +681,7 @@ char *script; #if USE_SCRIPT_FATFS>=0 fsp=&SD; - -#ifdef USE_MMC - if (fsp->begin()) { -#else if (SD.begin(USE_SCRIPT_FATFS)) { -#endif - #else if (fsp->begin()) { #endif @@ -738,13 +762,14 @@ float median_array(float *array,uint8_t len) { } -float *Get_MFAddr(uint8_t index,uint8_t *len) { +float *Get_MFAddr(uint8_t index,uint8_t *len,uint8_t *ipos) { *len=0; uint8_t *mp=(uint8_t*)glob_script_mem.mfilt; for (uint8_t count=0; countnumvals&0x7f; + if (ipos) *ipos=mflp->index; return mflp->rbuff; } mp+=sizeof(struct M_FILT)+((mflp->numvals&0x7f)-1)*sizeof(float); @@ -936,6 +961,56 @@ if (hsv.S == 0) { #endif //#endif +#ifdef USE_ANGLE_FUNC +uint32_t pulse_time_hl; +uint32_t pulse_time_lh; +uint32_t pulse_ltime_hl; +uint32_t pulse_ltime_lh; +uint8_t pt_pin; + +void MP_Timer(void) ICACHE_RAM_ATTR; + +#define MPT_DEBOUNCE 10 + +void MP_Timer(void) { + uint32_t level = digitalRead(pt_pin&0x3f); + uint32_t ms = millis(); + uint32_t time; + if (level) { + // rising edge + pulse_ltime_lh = ms; + time = ms - pulse_ltime_hl; + if (time>MPT_DEBOUNCE) pulse_time_hl = time; + } else { + // falling edge + pulse_ltime_hl = ms; + time = ms - pulse_ltime_lh; + if (time>MPT_DEBOUNCE) pulse_time_lh = time; + } +} + +uint32_t MeasurePulseTime(int32_t in) { + if (in >= 0) { + // define pin; + pt_pin = in; + pinMode(pt_pin&0x3f,INPUT_PULLUP); + attachInterrupt(pt_pin&0x3f, MP_Timer, CHANGE); + pulse_ltime_lh = millis(); + pulse_ltime_hl = millis(); + return 0; + } + uint32_t ptime; + if (in==-1) { + ptime = pulse_time_lh; + pulse_time_lh = 0; + } else { + ptime = pulse_time_hl; + pulse_time_hl = 0; + } + return ptime; +} +#endif // USE_ANGLE_FUNC + // vtype => ff=nothing found, fe=constant number,fd = constant string else bit 7 => 80 = string, 0 = number // no flash strings here for performance reasons!!! char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,JsonObject *jo) { @@ -1720,6 +1795,15 @@ chknext: len=0; goto exit; } +#ifdef USE_ANGLE_FUNC + if (!strncmp(vname,"mpt(",4)) { + lp=GetNumericResult(lp+4,OPER_EQU,&fvar,0); + fvar=MeasurePulseTime(fvar); + lp++; + len=0; + goto exit; + } +#endif if (!strncmp(vname,"micros",6)) { fvar=micros(); goto exit; @@ -3159,7 +3243,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { // numeric result if (glob_script_mem.type[ind.index].bits.is_filter) { uint8_t len=0; - float *fa=Get_MFAddr(index,&len); + float *fa=Get_MFAddr(index,&len,0); //Serial.printf(">> 2 %d\n",(uint32_t)*fa); if (fa && len) ws2812_set_array(fa,len,fvar); } @@ -4065,26 +4149,26 @@ void ScriptSaveSettings(void) { } -#if defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) +#ifdef EEP_SCRIPT_SIZE if (glob_script_mem.flags&1) { EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); } -#endif +#endif // EEP_SCRIPT_SIZE -#if !defined(USE_24C256) && defined(USE_SCRIPT_FATFS) +#ifdef USE_SCRIPT_FATFS if (glob_script_mem.flags&1) { fsp->remove(FAT_SCRIPT_NAME); File file=fsp->open(FAT_SCRIPT_NAME,FILE_WRITE); file.write((const uint8_t*)glob_script_mem.script_ram,FAT_SCRIPT_SIZE); file.close(); } -#endif +#endif // USE_SCRIPT_FATFS -#if defined(LITTLEFS_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) +#ifdef LITTLEFS_SCRIPT_SIZE if (glob_script_mem.flags&1) { SaveFile("/script.txt",(uint8_t*)glob_script_mem.script_ram,LITTLEFS_SCRIPT_SIZE); } -#endif +#endif // LITTLEFS_SCRIPT_SIZE } if (glob_script_mem.script_mem) { @@ -4095,10 +4179,6 @@ void ScriptSaveSettings(void) { } #ifdef USE_SCRIPT_COMPRESSION -#ifndef USE_24C256 -#ifndef USE_SCRIPT_FATFS -#ifndef LITTLEFS_SCRIPT_SIZE - //AddLog_P2(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram)); uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1); if (len_compressed > 0) { @@ -4107,10 +4187,6 @@ void ScriptSaveSettings(void) { } else { AddLog_P2(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed); } - -#endif -#endif -#endif #endif // USE_SCRIPT_COMPRESSION if (bitRead(Settings.rule_enabled, 0)) { @@ -5068,10 +5144,11 @@ const char SCRIPT_MSG_GTE1[] PROGMEM = "'%s'"; #define MAX_GARRAY 4 -char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint8_t *rentries) { +char *gc_get_arrays(char *lp, float **arrays, uint8_t *ranum, uint8_t *rentries, uint8_t *ipos) { struct T_INDEX ind; uint8_t vtype; uint8 entries=0; +uint8_t cipos=0; uint8_t anum=0; while (anum> 2 %d\n",(uint32_t)*fa); if (fa && len>=entries) { - if (!entries) {entries = len;} + if (!entries) { + entries = len; + } // add array to list arrays[anum]=fa; anum++; @@ -5111,6 +5190,7 @@ uint8 entries=0; //Serial.printf(">> %d - %d - %d\n",anum,entries,(uint32_t)*arrays[0]); *ranum=anum; *rentries=entries; + *ipos=cipos; return lp; } @@ -5409,7 +5489,8 @@ void ScriptWebShow(char mc) { float *arrays[MAX_GARRAY]; uint8_t anum=0; uint8 entries=0; - lp=gc_get_arrays(lp, &arrays[0], &anum, &entries); + uint8 ipos=0; + lp=gc_get_arrays(lp, &arrays[0], &anum, &entries, &ipos); if (anum>nanum) { goto nextwebline; @@ -5456,28 +5537,38 @@ void ScriptWebShow(char mc) { int8_t todflg=-1; if (!strncmp(label,"cnt",3)) { todflg=atoi(&label[3]); + if (todflg>=entries) todflg=entries-1; } + uint32_t aind=ipos; + if (aind>=entries) aind=entries-1; for (uint32_t cnt=0; cnt=0) { sprintf(lbl,"%d",todflg); todflg++; + if (todflg>=entries) { + todflg=0; + } } else { - GetTextIndexed(lbl, sizeof(lbl), cnt, label); + GetTextIndexed(lbl, sizeof(lbl), aind, label); } WSContentSend_PD(lbl); WSContentSend_PD("',"); for (uint32_t ind=0; ind=entries) { + aind=0; + } } // get header @@ -5722,7 +5813,7 @@ uint32_t scripter_create_task(uint32_t num, uint32_t time, uint32_t core) { /*********************************************************************************************\ * Interface \*********************************************************************************************/ - +//const esp_partition_t *esp32_part; bool Xdrv10(uint8_t function) { @@ -5740,9 +5831,6 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram_size=PMEM_SIZE; #ifdef USE_SCRIPT_COMPRESSION -#ifndef USE_24C256 -#ifndef USE_SCRIPT_FATFS -#ifndef LITTLEFS_SCRIPT_SIZE int32_t len_decompressed; sprt=(char*)calloc(UNISHOXRSIZE+8,1); if (!sprt) { break; } @@ -5751,9 +5839,6 @@ bool Xdrv10(uint8_t function) len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size); if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed]=0; //AddLog_P2(LOG_LEVEL_INFO, PSTR("decompressed script len %d"),len_decompressed); -#endif -#endif -#endif #endif // USE_SCRIPT_COMPRESSION #ifdef USE_BUTTON_EVENT @@ -5762,10 +5847,8 @@ bool Xdrv10(uint8_t function) } #endif -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS - if (I2cEnabled(XI2C_37)) { - if (I2cSetDevice(EEPROM_ADDRESS)) { +#ifdef EEP_SCRIPT_SIZE + if (eeprom_init(EEP_SCRIPT_SIZE)) { // found 32kb eeprom char *script; script=(char*)calloc(EEP_SCRIPT_SIZE+4,1); @@ -5782,34 +5865,26 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; glob_script_mem.flags=1; - I2cSetActiveFound(EEPROM_ADDRESS, "EEPROM"); - } } -#endif -#endif +#endif // EEP_SCRIPT_SIZE #ifdef USE_SCRIPT_FATFS #if USE_SCRIPT_FATFS>=0 - fsp = &SD; - -#ifdef USE_MMC - if (fsp->begin()) { -#else - + // fs on SD card #ifdef ESP32 if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO) && PinUsed(GPIO_SPI_CLK)) { - SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1); + SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1); } -#endif +#endif // ESP32 + fsp = &SD; if (SD.begin(USE_SCRIPT_FATFS)) { -#endif - #else - fsp = &LittleFS; - if (fsp->begin()) { -#endif + // fs on flash + fsp = &LittleFS; + if (fsp->begin()) { +#endif // USE_SCRIPT_FATFS>=0 //fsp->dateTimeCallback(dateTime); @@ -5834,14 +5909,18 @@ bool Xdrv10(uint8_t function) } else { glob_script_mem.script_sd_found=0; } -#endif +#endif // USE_SCRIPT_FATFS -#if defined(LITTLEFS_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) +#ifdef LITTLEFS_SCRIPT_SIZE #ifdef ESP32 + // spiffs on esp32 fsp = &SPIFFS; + //esp32_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,ESP_PARTITION_SUBTYPE_DATA_SPIFFS,NULL); + //Serial.printf("address %d - %d - %s\n",esp32_part->address,esp32_part->size, esp32_part->label); #else + // lfs on esp8266 fsp = &LittleFS; #endif char *script; @@ -5856,7 +5935,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_pram=(uint8_t*)Settings.rules[0]; glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; glob_script_mem.flags=1; -#endif +#endif // LITTLEFS_SCRIPT_SIZE // a valid script MUST start with >D if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') {