diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 767ea4f28..89dbff873 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -209,7 +209,6 @@ void loop(void); #include "WString.h" #include "HardwareSerial.h" -#include "FileSystem.h" #include "Esp.h" #include "debug.h" diff --git a/cores/esp8266/FileSystem.cpp b/cores/esp8266/FileSystem.cpp deleted file mode 100644 index 1d2a10f0d..000000000 --- a/cores/esp8266/FileSystem.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* - FileSystem.cpp - SPIFS implementation for esp8266 - - Copyright (c) 2015 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "FileSystem.h" -#include "Arduino.h" -#include "spiffs/spiffs_esp8266.h" - -// These addresses and sizes are defined in the linker script. -// For each flash memory size there is a linker script variant -// which sets spiffs location and size. -extern "C" uint32_t _SPIFFS_start; -extern "C" uint32_t _SPIFFS_end; -extern "C" uint32_t _SPIFFS_page; -extern "C" uint32_t _SPIFFS_block; - -static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst); -static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src); -static s32_t api_spiffs_erase(u32_t addr, u32_t size); - -FSClass FS((uint32_t) &_SPIFFS_start, (uint32_t) &_SPIFFS_end, (uint32_t) &_SPIFFS_page, (uint32_t) &_SPIFFS_block, 4); - -FSClass::FSClass(uint32_t beginAddress, uint32_t endAddress, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFiles) -: _beginAddress(beginAddress) -, _endAddress(endAddress) -, _pageSize(pageSize) -, _blockSize(blockSize) -, _maxOpenFiles(maxOpenFiles) -, _fs({0}) -{ -} - -int FSClass::_mountInternal(){ - if (_beginAddress == 0 || _beginAddress >= _endAddress){ - SPIFFS_API_DBG_E("Can't start file system, wrong address\r\n"); - return SPIFFS_ERR_NOT_CONFIGURED; - } - if(_pageSize == 0) _pageSize = 256; - if(_blockSize == 0) _blockSize = 4096; - - spiffs_config cfg = {0}; - cfg.phys_addr = _beginAddress; - cfg.phys_size = _endAddress - _beginAddress; - cfg.phys_erase_block = INTERNAL_FLASH_SECTOR_SIZE; - cfg.log_block_size = _blockSize; - cfg.log_page_size = _pageSize; - cfg.hal_read_f = api_spiffs_read; - cfg.hal_write_f = api_spiffs_write; - cfg.hal_erase_f = api_spiffs_erase; - - SPIFFS_API_DBG_V("FSClass::_mountInternal: start:%x, size:%d Kb\n", cfg.phys_addr, cfg.phys_size / 1024); - - _work.reset(new uint8_t[2*_pageSize]); - _fdsSize = 32 * _maxOpenFiles; - _fds.reset(new uint8_t[_fdsSize]); - _cacheSize = (32 + _pageSize) * _maxOpenFiles; - _cache.reset(new uint8_t[_cacheSize]); - - s32_t res = SPIFFS_mount(&_fs, - &cfg, - _work.get(), - _fds.get(), - _fdsSize, - _cache.get(), - _cacheSize, - NULL); - SPIFFS_API_DBG_V("FSClass::_mountInternal: %d\n", res); - return res; -} - -bool FSClass::mount() { - if(SPIFFS_mounted(&_fs)) - return true; - - int res = _mountInternal(); - if(res != SPIFFS_OK){ - int formated = SPIFFS_format(&_fs); - if(formated != SPIFFS_OK) - return false; - res = _mountInternal(); - } - return (res == SPIFFS_OK); -} - -// TODO: need to invalidate open file objects -void FSClass::unmount() { - if(SPIFFS_mounted(&_fs)) - SPIFFS_unmount(&_fs); -} - -bool FSClass::format() { - if(!SPIFFS_mounted(&_fs)){ - _mountInternal(); - } - SPIFFS_unmount(&_fs); - int formated = SPIFFS_format(&_fs); - if(formated != SPIFFS_OK) - return false; - return (_mountInternal() == SPIFFS_OK); -} - -bool FSClass::check() { - return SPIFFS_check(&_fs) == SPIFFS_OK; -} - -bool FSClass::exists(char *filename) { - spiffs_stat stat = {0}; - if (SPIFFS_stat(&_fs, filename, &stat) < 0) - return false; - return stat.name[0] != '\0'; -} - -bool FSClass::create(char *filepath){ - return SPIFFS_creat(&_fs, filepath, 0) == SPIFFS_OK; -} - -bool FSClass::remove(char *filepath){ - return SPIFFS_remove(&_fs, filepath) == SPIFFS_OK; -} - -bool FSClass::rename(char *filename, char *newname) { - return SPIFFS_rename(&_fs, filename, newname) == SPIFFS_OK; -} - -size_t FSClass::totalBytes(){ - u32_t totalBytes; - u32_t usedBytes; - if(SPIFFS_info(&_fs, &totalBytes, &usedBytes) == SPIFFS_OK) - return totalBytes; - return 0; -} - -size_t FSClass::usedBytes(){ - u32_t totalBytes; - u32_t usedBytes; - if(SPIFFS_info(&_fs, &totalBytes, &usedBytes) == SPIFFS_OK) - return usedBytes; - return 0; -} - -FSFile FSClass::open(char *filename, uint8_t mode) { - if(strcmp(filename, "") == 0 || - strcmp(filename, "/") == 0) - return FSFile(&_fs, "/"); - - int repeats = 0; - bool notExist; - bool canRecreate = (mode & SPIFFS_CREAT) == SPIFFS_CREAT; - int res; - - do{ - notExist = false; - res = SPIFFS_open(&_fs, filename, (spiffs_flags)mode, 0); - int code = SPIFFS_errno(&_fs); - if (res < 0){ - SPIFFS_API_DBG_E("open errno %d\n", code); - notExist = (code == SPIFFS_ERR_NOT_FOUND || code == SPIFFS_ERR_DELETED || code == SPIFFS_ERR_FILE_DELETED || code == SPIFFS_ERR_IS_FREE); - if (notExist && canRecreate) - remove(filename); // fix for deleted files - } - } while (notExist && canRecreate && repeats++ < 3); - - if(res){ - return FSFile(&_fs, res); - } - return FSFile(); -} - -FSFile FSClass::open(spiffs_dirent* entry, uint8_t mode){ - int res = SPIFFS_open_by_dirent(&_fs, entry, (spiffs_flags)mode, 0); - if (res){ - return FSFile(&_fs, res); - } - return FSFile(); -} - -FSFile::FSFile() -: _file(0) -, _stats({0}) -, _fs(0) -{ -} - -FSFile::FSFile(spiffs* fs, String path) -: _fs(fs) -{ - if(path == "/"){ - _file = 0x1; - os_sprintf((char*)_stats.name, "%s", (char*)path.c_str()); - _stats.size = 0; - _stats.type = SPIFFS_TYPE_DIR; - SPIFFS_opendir(_fs, (char*)_stats.name, &_dir); - } else { - _file = SPIFFS_open(_fs, (char *)path.c_str(), (spiffs_flags)FSFILE_READ, 0); - if(SPIFFS_fstat(_fs, _file, &_stats) != 0){ - SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(_fs)); - } - //debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); - if(_stats.type == SPIFFS_TYPE_DIR){ - SPIFFS_opendir(_fs, (char*)_stats.name, &_dir); - } - } -} - -FSFile::FSFile(spiffs* fs, file_t f) -: _file(f) -, _fs(fs) -{ - if(SPIFFS_fstat(_fs, _file, &_stats) != 0){ - SPIFFS_API_DBG_E("fstat errno %d\n", SPIFFS_errno(_fs)); - } - //debugf("FSFile name: %s, size: %d, type: %d\n", _stats.name, _stats.size, _stats.type); - if(_stats.type == SPIFFS_TYPE_DIR){ - SPIFFS_opendir(_fs, (char*)_stats.name, &_dir); - } -} - -void FSFile::close() { - if (!_file) - return; - if(_stats.type == SPIFFS_TYPE_DIR){ - SPIFFS_closedir(&_dir); - } - if(os_strlen((char*)_stats.name) > 1) - SPIFFS_close(_fs, _file); - _file = 0; -} - -char * FSFile::name(){ - return (char*)_stats.name; -} - -bool FSFile::isDirectory(void) { - return _stats.type == SPIFFS_TYPE_DIR; -} - -void FSFile::rewindDirectory() { - if (!_file || !isDirectory()) - return; - SPIFFS_closedir(&_dir); - SPIFFS_opendir(_fs, (char*)_stats.name, &_dir); -} - -FSFile FSFile::openNextFile(){ - if (!_file || !isDirectory()) - return FSFile(); - struct spiffs_dirent e; - struct spiffs_dirent *pe = &e; - if ((pe = SPIFFS_readdir(&_dir, pe))){ - // TODO: store actual FS pointer - return FS.open((char *)pe->name); - } - return FSFile(); -} - -uint32_t FSFile::size() { - if(!_file) - return 0; - if(_stats.size) - return _stats.size; - uint32_t pos = SPIFFS_tell(_fs, _file); - SPIFFS_lseek(_fs, _file, 0, SPIFFS_SEEK_END); - _stats.size = SPIFFS_tell(_fs, _file); - SPIFFS_lseek(_fs, _file, pos, SPIFFS_SEEK_SET); - return _stats.size; -} - -int FSFile::available() { - if (!_file) - return 0; - uint32_t pos = SPIFFS_tell(_fs, _file); - return size() - pos; -} - -uint32_t FSFile::seek(uint32_t pos) { - if (!_file) - return 0; - return SPIFFS_lseek(_fs, _file, pos, SPIFFS_SEEK_SET); -} - -uint32_t FSFile::position() { - if (!_file) - return 0; - return SPIFFS_tell(_fs, _file); -} - -bool FSFile::eof() { - if (!_file) - return 0; - return SPIFFS_eof(_fs, _file); -} - -int FSFile::read(void *buf, uint16_t nbyte) { - if (!_file || isDirectory()) - return -1; - return SPIFFS_read(_fs, _file, buf, nbyte); -} - -int FSFile::read() { - if (! _file || isDirectory()) - return -1; - int val; - if(SPIFFS_read(_fs, _file, &val, 1) != 1) return -1; - return val; -} - -int FSFile::peek() { - if (!_file || isDirectory()) - return 0; - int c = read(); - SPIFFS_lseek(_fs, _file, -1, SPIFFS_SEEK_CUR); - return c; -} - -size_t FSFile::write(const uint8_t *buf, size_t size){ - if (!_file || isDirectory()) - return 0; - int res = SPIFFS_write(_fs, _file, (uint8_t *)buf, size); - return (res > 0)?(size_t)res:0; -} - -size_t FSFile::write(uint8_t val) { - if (!_file || isDirectory()) - return 0; - return write(&val, 1); -} - -void FSFile::flush(){ - if (!_file || isDirectory()) - return; - SPIFFS_fflush(_fs, _file); -} - -bool FSFile::remove(){ - if (!_file) - return 0; - close(); - return SPIFFS_remove(_fs, (char *)_stats.name) == 0; -} - -int FSFile::lastError(){ - return SPIFFS_errno(_fs); -} - -void FSFile::clearError(){ - _fs->err_code = SPIFFS_OK; -} - - -static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst){ - SPIFFS_API_DBG_V("api_spiffs_read: 0x%08x len: %u\n", addr, size); - flashmem_read(dst, addr, size); - return SPIFFS_OK; -} - -static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){ - SPIFFS_API_DBG_V("api_spiffs_write: 0x%08x len: %u\n", addr, size); - flashmem_write(src, addr, size); - return SPIFFS_OK; -} - -static s32_t api_spiffs_erase(u32_t addr, u32_t size){ - SPIFFS_API_DBG_V("api_spiffs_erase: 0x%08x len: %u\n", addr, size); - u32_t sect_first = flashmem_get_sector_of_address(addr); - u32_t sect_last = flashmem_get_sector_of_address(addr+size); - while( sect_first <= sect_last ) - if( !flashmem_erase_sector( sect_first ++ ) ) - return SPIFFS_ERR_INTERNAL; - return SPIFFS_OK; -} - - diff --git a/cores/esp8266/FileSystem.h b/cores/esp8266/FileSystem.h deleted file mode 100644 index fc0906dbb..000000000 --- a/cores/esp8266/FileSystem.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - FileSystem.h - SPIFS implementation for esp8266 - - Copyright (c) 2015 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifndef _SPIFFS_CORE_FILESYSTEM_H_ -#define _SPIFFS_CORE_FILESYSTEM_H_ - -#include -#include "spiffs/spiffs.h" -#include "Arduino.h" - -#define FSFILE_READ SPIFFS_RDONLY -#define FSFILE_WRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND ) -#define FSFILE_OVERWRITE (SPIFFS_RDONLY | SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_TRUNC ) - -class FSFile : public Stream { -private: - spiffs_stat _stats; - file_t _file; - spiffs_DIR _dir; - spiffs * _fs; - -public: - FSFile(spiffs* fs, String path); - FSFile(spiffs* fs, file_t f); - FSFile(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual int read(); - virtual int peek(); - virtual int available(); - virtual void flush(); - int read(void *buf, uint16_t nbyte); - uint32_t seek(uint32_t pos); - uint32_t position(); - uint32_t size(); - bool eof(); - void close(); - bool remove(); - int lastError(); - void clearError(); - operator bool() { return _file > 0; } - char * name(); - bool isDirectory(void); - void rewindDirectory(void); - FSFile openNextFile(void); - - template size_t write(T &src){ - const size_t bufferSize = 64; - uint8_t obuf[bufferSize]; - size_t bytesWritten = 0; - while (true){ - size_t available = src.available(); - if(!available) - return bytesWritten; - size_t willWrite = (available < bufferSize) ? available : bufferSize; - src.read(obuf, willWrite); - size_t cb = write(obuf, willWrite); - if (cb != willWrite) { - return bytesWritten; - } - bytesWritten += cb; - } - return bytesWritten; - } - - using Print::write; -}; - -class FSClass { -public: - FSClass(uint32_t beginAddress, uint32_t endAddress, uint32_t pageSize, uint32_t blockSize, uint32_t maxOpenFiles); - - bool mount(); - void unmount(); - bool format(); - bool check(); - bool exists(char *filename); - bool create(char *filepath); - bool remove(char *filepath); - bool rename(char *filename, char *newname); - size_t totalBytes(); - size_t usedBytes(); - size_t size(){ return _fs.cfg.phys_size; } - size_t blockSize(){ return _fs.cfg.log_block_size; } - size_t totalBlocks(){ return _fs.block_count; } - size_t freeBlocks(){ return _fs.free_blocks; } - size_t pageSize(){ return _fs.cfg.log_page_size; } - size_t allocatedPages(){ return _fs.stats_p_allocated; } - size_t deletedPages(){ return _fs.stats_p_deleted; } - - FSFile open(char *filename, uint8_t mode = FSFILE_READ); - FSFile open(spiffs_dirent* entry, uint8_t mode = FSFILE_READ); - -protected: - int _mountInternal(); - std::unique_ptr _work; - std::unique_ptr _fds; - size_t _fdsSize; - std::unique_ptr _cache; - size_t _cacheSize; - uint32_t _beginAddress; - uint32_t _endAddress; - uint32_t _pageSize; - uint32_t _blockSize; - uint32_t _maxOpenFiles; - spiffs _fs; - - -private: - friend class FSFile; -}; - -extern FSClass FS; - -#endif diff --git a/cores/esp8266/spiffs/spiffs_esp8266.c b/cores/esp8266/spiffs/spiffs_esp8266.c deleted file mode 100644 index 7cd4fd684..000000000 --- a/cores/esp8266/spiffs/spiffs_esp8266.c +++ /dev/null @@ -1,164 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/anakod/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - ****/ - -#include "spiffs_esp8266.h" -#include "spi_flash.h" -#include "esp8266_peri.h" -#include "Arduino.h" - -/* - FLASH ACCESS FUNCTIONS -*/ - -//lowest level sector erase method -bool flashmem_erase_sector( uint32_t sector_id ){ - WDT_RESET(); - noInterrupts(); - uint32_t chip_size = flashchip->chip_size; - flashchip->chip_size = 0x01000000; - bool erased = spi_flash_erase_sector( sector_id ) == SPI_FLASH_RESULT_OK; - flashchip->chip_size = chip_size; - interrupts(); - return erased; -} - -//lowest level data write method -uint32_t flashmem_write_internal( const void *from, uint32_t toaddr, uint32_t size ){ - toaddr -= INTERNAL_FLASH_START_ADDRESS; - SpiFlashOpResult r; - const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; - uint32_t *apbuf = NULL; - if(((uint32_t)from) & blkmask){ - apbuf = (uint32_t *)os_malloc(size); - if(!apbuf) - return 0; - os_memcpy(apbuf, from, size); - } - WDT_RESET(); - noInterrupts(); - uint32_t chip_size = flashchip->chip_size; - flashchip->chip_size = 0x01000000; - r = spi_flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size); - flashchip->chip_size = chip_size; - interrupts(); - if(apbuf) - os_free(apbuf); - if(SPI_FLASH_RESULT_OK == r) - return size; - else{ - SPIFFS_API_DBG_E( "ERROR in flash_write: r=%d at %08X\n", ( int )r, ( unsigned )toaddr+INTERNAL_FLASH_START_ADDRESS ); - return 0; - } -} - -//lowest level data read method -uint32_t flashmem_read_internal( void *to, uint32_t fromaddr, uint32_t size ){ - fromaddr -= INTERNAL_FLASH_START_ADDRESS; - SpiFlashOpResult r; - WDT_RESET(); - noInterrupts(); - uint32_t chip_size = flashchip->chip_size; - flashchip->chip_size = 0x01000000; - r = spi_flash_read(fromaddr, (uint32 *)to, size); - flashchip->chip_size = chip_size; - interrupts(); - if(SPI_FLASH_RESULT_OK == r) - return size; - else{ - SPIFFS_API_DBG_E( "ERROR in flash_read: r=%d at %08X\n", ( int )r, ( unsigned )fromaddr+INTERNAL_FLASH_START_ADDRESS ); - return 0; - } -} - -//mid level data write method -uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ){ - uint32_t temp, rest, ssize = size; - unsigned i; - char tmpdata[ INTERNAL_FLASH_WRITE_UNIT_SIZE ]; - const uint8_t *pfrom = ( const uint8_t* )from; - const uint32_t blksize = INTERNAL_FLASH_WRITE_UNIT_SIZE; - const uint32_t blkmask = INTERNAL_FLASH_WRITE_UNIT_SIZE - 1; - - // Align the start - if(toaddr & blkmask){ - rest = toaddr & blkmask; - temp = toaddr & ~blkmask; // this is the actual aligned address - // c_memcpy( tmpdata, ( const void* )temp, blksize ); - flashmem_read_internal( tmpdata, temp, blksize ); - for( i = rest; size && ( i < blksize ); i ++, size --, pfrom ++ ) - tmpdata[ i ] = *pfrom; - flashmem_write_internal( tmpdata, temp, blksize ); - if( size == 0 ) - return ssize; - toaddr = temp + blksize; - } - // The start address is now a multiple of blksize - // Compute how many bytes we can write as multiples of blksize - rest = size & blkmask; - temp = size & ~blkmask; - // Program the blocks now - if(temp){ - flashmem_write_internal( pfrom, toaddr, temp ); - toaddr += temp; - pfrom += temp; - } - // And the final part of a block if needed - if(rest){ - // c_memcpy( tmpdata, ( const void* )toaddr, blksize ); - flashmem_read_internal( tmpdata, toaddr, blksize ); - for( i = 0; size && ( i < rest ); i ++, size --, pfrom ++ ) - tmpdata[ i ] = *pfrom; - flashmem_write_internal( tmpdata, toaddr, blksize ); - } - return ssize; -} - -//mid level data write method -uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ){ - uint32_t temp, rest, ssize = size; - unsigned i; - char tmpdata[ INTERNAL_FLASH_READ_UNIT_SIZE ]; - uint8_t *pto = ( uint8_t* )to; - const uint32_t blksize = INTERNAL_FLASH_READ_UNIT_SIZE; - const uint32_t blkmask = INTERNAL_FLASH_READ_UNIT_SIZE - 1; - - // Align the start - if(fromaddr & blkmask){ - rest = fromaddr & blkmask; - temp = fromaddr & ~blkmask; // this is the actual aligned address - flashmem_read_internal( tmpdata, temp, blksize ); - for( i = rest; size && ( i < blksize ); i ++, size --, pto ++ ) - *pto = tmpdata[ i ]; - - if( size == 0 ) - return ssize; - fromaddr = temp + blksize; - } - // The start address is now a multiple of blksize - // Compute how many bytes we can read as multiples of blksize - rest = size & blkmask; - temp = size & ~blkmask; - // Program the blocks now - if(temp){ - flashmem_read_internal( pto, fromaddr, temp ); - fromaddr += temp; - pto += temp; - } - // And the final part of a block if needed - if(rest){ - flashmem_read_internal( tmpdata, fromaddr, blksize ); - for( i = 0; size && ( i < rest ); i ++, size --, pto ++ ) - *pto = tmpdata[ i ]; - } - return ssize; -} - -//shorthand when start and end addresses of the sector are not needed -uint32_t flashmem_get_sector_of_address( uint32_t addr ){ - return (addr - INTERNAL_FLASH_START_ADDRESS) / INTERNAL_FLASH_SECTOR_SIZE; -} - diff --git a/cores/esp8266/spiffs/spiffs_esp8266.h b/cores/esp8266/spiffs/spiffs_esp8266.h deleted file mode 100644 index cd1eb3544..000000000 --- a/cores/esp8266/spiffs/spiffs_esp8266.h +++ /dev/null @@ -1,42 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/anakod/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - ****/ - -#ifndef SYSTEM_FLASHMEM_H_ -#define SYSTEM_FLASHMEM_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "spiffs.h" - -/******************* -The W25Q32BV array is organized into 16,384 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. -Pages can be erased in groups of 16 (4KB sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or -the entire chip (chip erase). The W25Q32BV has 1,024 erasable sectors and 64 erasable blocks respectively. -The small 4KB sectors allow for greater flexibility in applications that require data and parameter storage. -********************/ - -#define SPIFFS_API_DBG_V(fmt, ...) //os_printf(fmt, ##__VA_ARGS__) -#define SPIFFS_API_DBG_E(fmt, ...) //os_printf("ERROR: " fmt , ##__VA_ARGS__) - -#define INTERNAL_FLASH_SECTOR_SIZE 4096 -#define INTERNAL_FLASH_START_ADDRESS 0x40200000 - -#define INTERNAL_FLASH_WRITE_UNIT_SIZE 4 -#define INTERNAL_FLASH_READ_UNIT_SIZE 4 - -extern uint32_t flashmem_write( const void *from, uint32_t toaddr, uint32_t size ); -extern uint32_t flashmem_read( void *to, uint32_t fromaddr, uint32_t size ); -extern bool flashmem_erase_sector( uint32_t sector_id ); -uint32_t flashmem_get_sector_of_address( uint32_t addr ); - -#ifdef __cplusplus -} -#endif - -#endif /* SYSTEM_FLASHMEM_H_ */ diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/FSWebServer.ino b/libraries/ESP8266WebServer/examples/FSWebServer/FSWebServer.ino deleted file mode 100644 index 12d7a20c2..000000000 --- a/libraries/ESP8266WebServer/examples/FSWebServer/FSWebServer.ino +++ /dev/null @@ -1,273 +0,0 @@ -/* - FSWebServer - Example WebServer with SPIFFS backend for esp8266 - - Copyright (c) 2015 Hristo Gochkov. All rights reserved. - This file is part of the ESP8266WebServer library for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) - !!! This will erase any previous SPIFFS data you may have! - !!! Make Backups First !!! - if you do not have it, get it at : << -#include -#include -#include -#include - -#define DBG_OUTPUT_PORT Serial - -const char* ssid = "**********"; -const char* password = "**********"; -const char* hostname = "esp8266fs"; - -MDNSResponder mdns; -ESP8266WebServer server(80); -//holds the current upload -FSFile fsUploadFile; - -//format bytes -char *formatBytes(size_t bytes){ - if (bytes < 1024){ - return (char *)String(String(bytes)+"B").c_str(); - } else if(bytes < (1024 * 1024)){ - return (char *)String(String(bytes/1024.0)+"KB").c_str(); - } else if(bytes < (1024 * 1024 * 1024)){ - return (char *)String(String(bytes/1024.0/1024.0)+"MB").c_str(); - } else { - return (char *)String(String(bytes/1024.0/1024.0/1024.0)+"GB").c_str(); - } -} - -String getContentType(String filename){ - if(server.hasArg("download")) return "application/octet-stream"; - else if(filename.endsWith(".htm")) return "text/html"; - else if(filename.endsWith(".css")) return "text/css"; - else if(filename.endsWith(".js")) return "application/javascript"; - else if(filename.endsWith(".png")) return "image/png"; - else if(filename.endsWith(".gif")) return "image/gif"; - else if(filename.endsWith(".jpg")) return "image/jpeg"; - else if(filename.endsWith(".ico")) return "image/x-icon"; - else if(filename.endsWith(".xml")) return "text/xml"; - else if(filename.endsWith(".pdf")) return "application/x-pdf"; - else if(filename.endsWith(".zip")) return "application/x-zip"; - else if(filename.endsWith(".gz")) return "application/x-gzip"; - return "text/plain"; -} - -bool handleFileRead(String path){ - if(path.endsWith("/")) path += "index.htm"; - String contentType = getContentType(path); - if(FS.exists((char *)(path+".gz").c_str()) || FS.exists((char *)path.c_str())){ - if(FS.exists((char *)(path+".gz").c_str())) - path += ".gz"; - FSFile file = FS.open((char *)path.c_str()); - server.streamFile(file, contentType); - file.close(); - return true; - } - return false; -} - -void handleFileUpdate(){ - if(server.uri() != "/edit") return; - HTTPUpload& upload = server.upload(); - if(upload.status == UPLOAD_FILE_START){ - String filename = upload.filename; - DBG_OUTPUT_PORT.print("Upload Name: "); DBG_OUTPUT_PORT.println(filename); - fsUploadFile = FS.open((char *)filename.c_str(), FSFILE_OVERWRITE); - filename = String(); - } else if(upload.status == UPLOAD_FILE_WRITE){ - //DBG_OUTPUT_PORT.print("Upload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize); - if(fsUploadFile) - fsUploadFile.write(upload.buf, upload.currentSize); - } else if(upload.status == UPLOAD_FILE_END){ - if(fsUploadFile) - fsUploadFile.close(); - DBG_OUTPUT_PORT.print("Upload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize); - } -} - -void handleFileDelete(){ - if(server.args() == 0) { - server.send(500, "text/plain", "BAD ARGS"); - return; - } - String path = server.arg(0); - if(path == "/") { - server.send(500, "text/plain", "BAD PATH"); - return; - } - if(!FS.exists((char *)(path.c_str()))) { - server.send(404, "text/plain", "FileNotFound"); - return; - } - FS.remove((char *)path.c_str()); - server.send(200, "text/plain", ""); - path = String(); -} - -void handleFileCreate(){ - if(server.args() == 0) { - server.send(500, "text/plain", "BAD ARGS"); - return; - } - String path = server.arg(0); - if(path == "/") { - server.send(500, "text/plain", "BAD PATH"); - return; - } - if(FS.exists((char *)path.c_str())) { - server.send(500, "text/plain", "FILE EXISTS"); - return; - } - FSFile file = FS.open((char *)path.c_str(), FSFILE_OVERWRITE); - if(file) - file.close(); - else { - server.send(500, "text/plain", "CREATE FAILED"); - return; - } - server.send(200, "text/plain", ""); - path = String(); -} - -void handleFileList() { - if(!server.hasArg("dir")) { - server.send(500, "text/plain", "BAD ARGS"); - return; - } - String path = server.arg("dir"); - - FSFile entry; - FSFile dir = FS.open((char *)path.c_str()); - path = String(); - if(!dir.isDirectory()){ - dir.close(); - server.send(500, "text/plain", "NOT DIR"); - return; - } - dir.rewindDirectory(); - - String output = "["; - while(true){ - entry = dir.openNextFile(); - if (!entry) - break; - - if(!FS.exists(entry.name())){ - os_printf("Entry[%s] Not Exists!\n", entry.name()); - entry.remove(); - entry.close(); - continue; - } - - if(output != "[") - output += ','; - output += "{\"type\":\""; - output += (entry.isDirectory())?"dir":"file"; - output += "\",\"name\":\""; - output += String(entry.name()).substring(1); - output += "\"}"; - entry.close(); - } - dir.close(); - - output += "]"; - server.send(200, "text/json", output); -} - -void setup(void){ - DBG_OUTPUT_PORT.begin(115200); - DBG_OUTPUT_PORT.print("\n"); - - //SPIFFS INIT - DBG_OUTPUT_PORT.printf("\n==== SPIFFS Info ====\n"); - DBG_OUTPUT_PORT.printf("FS Mount: %d\n", FS.mount()); - DBG_OUTPUT_PORT.printf("FS Size: %s\n", formatBytes(FS.size())); - DBG_OUTPUT_PORT.printf("FS Bytes: total: %s, used: %s\n", formatBytes(FS.totalBytes()), formatBytes(FS.usedBytes())); - DBG_OUTPUT_PORT.printf("FS Blocks: total: %d, free: %d, size: %s\n", FS.totalBlocks(), FS.freeBlocks(), formatBytes(FS.blockSize())); - DBG_OUTPUT_PORT.printf("FS Pages: allocated: %d, deleted: %d, size: %s\n", FS.allocatedPages(), FS.deletedPages(), formatBytes(FS.pageSize())); - FSFile entry; - FSFile dir = FS.open((char *)"/"); - while(true){ - entry = dir.openNextFile(); - if (!entry) break; - DBG_OUTPUT_PORT.printf("FS File: %s, type: %s, size: %s\n", entry.name(), (entry.isDirectory())?"dir":"file", formatBytes(entry.size())); - entry.close(); - } - dir.close(); - DBG_OUTPUT_PORT.printf("\n"); - - //WIFI INIT - DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid); - WiFi.begin(ssid, password); - if(WiFi.waitForConnectResult() != WL_CONNECTED){ - DBG_OUTPUT_PORT.printf("Could not connect to %s\n", ssid); - while(1) delay(500); - } - DBG_OUTPUT_PORT.print("Connected! IP address: "); - DBG_OUTPUT_PORT.println(WiFi.localIP()); - - //mDNS INIT - if (mdns.begin(hostname, WiFi.localIP())) - DBG_OUTPUT_PORT.printf("mDNS responder started for %s.local\n", hostname); - - //SERVER INIT - //list directory - server.on("/list", HTTP_GET, handleFileList); - //load editor - server.on("/edit", HTTP_GET, [](){ - if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound"); - }); - //create file - server.on("/edit", HTTP_PUT, handleFileCreate); - //delete file - server.on("/edit", HTTP_DELETE, handleFileDelete); - //called after file upload - server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }); - //called when a file is received inside POST data - server.onFileUpload(handleFileUpdate); - - //called when the url is not defined here - //use it to load content from SPIFFS - server.onNotFound([](){ - if(!handleFileRead(server.uri())) - server.send(404, "text/plain", "FileNotFound"); - }); - - //get heap status, analog input value and all GPIO statuses in one json call - server.on("/all", HTTP_GET, [](){ - String json = "{"; - json += "\"heap\":"+String(ESP.getFreeHeap()); - json += ", \"analog\":"+String(analogRead(A0)); - json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16))); - json += "}"; - server.send(200, "text/json", json); - json = String(); - }); - server.begin(); - DBG_OUTPUT_PORT.println("HTTP server started"); - -} - -void loop(void){ - server.handleClient(); -} diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/edit.htm.gz b/libraries/ESP8266WebServer/examples/FSWebServer/data/edit.htm.gz deleted file mode 100644 index 9ee1b81f0..000000000 Binary files a/libraries/ESP8266WebServer/examples/FSWebServer/data/edit.htm.gz and /dev/null differ diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/favicon.ico b/libraries/ESP8266WebServer/examples/FSWebServer/data/favicon.ico deleted file mode 100644 index 71b25fe6e..000000000 Binary files a/libraries/ESP8266WebServer/examples/FSWebServer/data/favicon.ico and /dev/null differ diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/graphs.js.gz b/libraries/ESP8266WebServer/examples/FSWebServer/data/graphs.js.gz deleted file mode 100644 index 72435445a..000000000 Binary files a/libraries/ESP8266WebServer/examples/FSWebServer/data/graphs.js.gz and /dev/null differ diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/index.htm b/libraries/ESP8266WebServer/examples/FSWebServer/data/index.htm deleted file mode 100644 index facca7b97..000000000 --- a/libraries/ESP8266WebServer/examples/FSWebServer/data/index.htm +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - ESP Monitor - - - - -
- - - - -
-
-
-
- - \ No newline at end of file diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit-src.htm b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit-src.htm deleted file mode 100644 index 980acc168..000000000 --- a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit-src.htm +++ /dev/null @@ -1,512 +0,0 @@ - - - - -ESP Editor - - - - - -
-
-
- - - - diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit.htm b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit.htm deleted file mode 100644 index cfd70baf7..000000000 --- a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/edit.htm +++ /dev/null @@ -1,3 +0,0 @@ -ESP Editor
diff --git a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/graphs-src.js b/libraries/ESP8266WebServer/examples/FSWebServer/data/src/graphs-src.js deleted file mode 100644 index 23a295587..000000000 --- a/libraries/ESP8266WebServer/examples/FSWebServer/data/src/graphs-src.js +++ /dev/null @@ -1,281 +0,0 @@ -/* - FSWebServer - Sample Graphing Library - - Copyright (c) 2015 Hristo Gochkov. All rights reserved. - This file is part of the ESP8266WebServer library for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ -function ce(t){ return document.createElement(t); } -function ac(a,b){ a.appendChild(b); } - -function createGraph(el, t, w, h, l, m, ib, tc, cb){ - if(typeof el === "undefined" || !el) return null; - if(typeof ib === "undefined" || !ib) ib = false; - w = (w>360)?w:360; - h = (h<100)?100:h; - var vs = new Array(); - var bgc = "black"; - var lc = (typeof tc === "undefined" && tc)?"yellow":tc; - var bc = "#444"; - var vcb = (typeof cb === "undefined" && cb)?null:cb; - var minV = m; - var maxV = 0; - var sv = 1; - var ov = l; - var gh = h+20; - - el.style.display = "block"; - el.style.backgroundColor = "#eee"; - el.style.border = "1px solid "+bc; - el.style.padding = "5px"; - el.style.margin = "5px"; - el.style.width = (w+2)+"px"; - - var g = ce("canvas"); - g.style.border = "1px solid "+bc; - g.style.marginTop = "5px"; - g.width = w; - g.height = gh; - - var c = g.getContext("2d"); - - var sl = ce("span"); - sl.innerText = "Scale: "; - sl.style.paddingLeft = "5px"; - - var st = ce("input"); - st.type = "text"; - st.size = 3; - st.value = sv; - st.onchange = function(e){ sv = st.value; }; - - var sm = ce("button"); - sm.innerText = "-"; - sm.onclick = function(e){ if(sv > 1) sv--; st.value = sv; }; - - var sp = ce("button"); - sp.innerText = "+"; - sp.onclick = function(e){ sv++; st.value = parseInt(sv); }; - - var ol = ce("span"); - ol.innerText = "Offset: "; - ol.style.paddingLeft = "5px"; - - var ot = ce("input"); - ot.type = "text"; - ot.size = 5; - ot.value = ov; - ot.onchange = function(e){ ov = parseInt(ot.value); }; - - var om = ce("button"); - om.innerText = "-"; - om.onclick = function(e){ if(ov > l) ov--; ot.value = ov; }; - - var op = ce("button"); - op.innerText = "+"; - op.onclick = function(e){ if(ov < m) ov++; ot.value = ov; }; - - ac(el,sl); - ac(el,sm); - ac(el,st); - ac(el,sp); - ac(el,ol); - ac(el,om); - ac(el,ot); - ac(el,op); - ac(el,ce("br")); - ac(el,g); - - function scv(v){ - if(v <= ov) return 0; - if(v > (((m - l) / sv) + ov)) return h; - return Math.round((v - ov) * (h / ((m - l) / sv))); - } - - g.add = function(v){ - if(vcb) v = vcb(v); - vs.push(v); - if(v < minV) minV = v; - if(v > maxV) maxV = v; - if(vs.length > w) vs.shift(); - c.canvas.width = w; - c.lineWidth = 1; - c.shadowBlur=2; - c.shadowColor="black"; - - c.fillStyle = bc; - c.fillRect(0, 0, w, 20); - c.fillStyle = lc; - c.font = "14px Verdana"; - var header = t+": "+(vs[vs.length - 1])+" | Min: "+minV+" | Max: "+maxV; - c.fillText(header,5,15); - - c.fillStyle = bgc; - c.fillRect(0, 20, w, gh); - c.strokeStyle = lc; - - for(var i = 0; i < vs.length; i++){ - if(ib){ - c.moveTo(i, gh); - c.lineTo(i, gh - scv(vs[i])); - c.stroke(); - continue; - } - if(i === 0){ - c.moveTo(0, gh - scv(vs[0])); - c.lineTo(0, gh - scv(vs[0])); - c.stroke(); - } else { - c.moveTo((i - 1), gh - scv(vs[i - 1])); - c.lineTo(i, gh - scv(vs[i])); - c.stroke(); - } - } - c.fillStyle = lc; - c.font = "10px Verdana"; - c.fillText(ov, 2, gh - 5); - c.fillText(Math.round((((m - l) / sv) + ov) * 10) / 10, 2, 30); - }; - return g; -} - -function createDigiGraph(el, t, w, h, m, tc){ - if(typeof el === "undefined" || !el) return null; - w = (w>360)?w:360; - h = (h<20)?20:h; - var vs = new Array(); - var bgc = "black"; - var lc = (typeof tc === "undefined" && tc)?"pink":tc; - var bc = "#444"; - var sv = 1; - var gh = h+20; - - el.style.display = "block"; - el.style.backgroundColor = "#eee"; - el.style.border = "1px solid "+bc; - el.style.padding = "5px"; - el.style.margin = "5px"; - el.style.width = (w+2)+"px"; - - var g = ce("canvas"); - g.style.border = "1px solid "+bc; - g.style.marginTop = "5px"; - g.width = w; - g.height = gh; - - var c = g.getContext("2d"); - - var sl = ce("span"); - sl.innerText = "Scale: "; - sl.style.paddingLeft = "5px"; - - var st = ce("input"); - st.type = "text"; - st.size = 3; - st.value = sv; - st.onchange = function(e){ sv = st.value; }; - - var sm = ce("button"); - sm.innerText = "-"; - sm.onclick = function(e){ if(sv > 1) sv--; st.value = sv; }; - - var sp = ce("button"); - sp.innerText = "+"; - sp.onclick = function(e){ sv++; st.value = parseInt(sv); }; - - ac(el,sl); - ac(el,sm); - ac(el,st); - ac(el,sp); - ac(el,ce("br")); - ac(el,g); - - function gpos(p){ - var each = Math.floor(((h - ((m.length - 1)*2))/m.length)); - var s = (p * 2) + (p * each); - return [s, s + each]; - } - - function gact(i,p){ - return ((vs[i] & (1 << m[p])) !== 0);; - } - - var vc = ["aqua","yellow","#FF4500","#00FF7F","orange","cyan","magenta","#7FFF00","#FAF0E6","#00CED1","#FFD700","#EE82EE","#00FF00","#00BFFF","#FF4500","#EEE8AA","#FF1493"]; - - g.add = function(v){ - vs.push(v); - if(vs.length > w) vs.shift(); - c.canvas.width = w; - c.lineWidth=1; - c.shadowBlur=2; - c.shadowColor="black"; - - c.fillStyle = bc; - c.fillRect(0, 0, w, 20); - c.fillStyle = lc; - c.font = "14px Verdana"; - c.fillText(t,5,15); - - c.fillStyle = bgc; - c.fillRect(0, 20, w, gh); - - c.strokeStyle = bc; - c.lineWidth = 1; - c.shadowBlur=0; - c.shadowColor=""; - for(var p=0;p35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('8 H(t){K 21.1Y(t)}8 9(a,b){a.1S(b)}8 1O(b,t,w,h,l,m,d,f,j){6(Q b==="S"||!b)K 1f;6(Q d==="S"||!d)d=1P;w=(w>1b)?w:1b;h=(h<1N)?1N:h;4 k=1M 1L();4 n="V";4 o=(Q f==="S"&&f)?"1J":f;4 p="#1I";4 q=(Q j==="S"&&j)?1f:j;4 r=m;4 s=0;4 u=1;4 x=l;4 y=h+20;b.7.1H="1G";b.7.1F="#1s";b.7.1c="12 11 "+p;b.7.1D="N";b.7.1C="N";b.7.P=(w+2)+"1B";4 g=H("1a");g.7.1c="12 11 "+p;g.7.1z="N";g.P=w;g.1w=y;4 c=g.1v("2d");4 z=H("1j");z.M="1u: ";z.7.1m="N";4 A=H("1p");A.1i="1r";A.1e=3;A.I=u;A.1h=8(e){u=A.I};4 B=H("T");B.M="-";B.U=8(e){6(u>1)u--;A.I=u};4 C=H("T");C.M="+";C.U=8(e){u++;A.I=1n(u)};4 D=H("1j");D.M="1Q: ";D.7.1m="N";4 E=H("1p");E.1i="1r";E.1e=5;E.I=x;E.1h=8(e){x=1n(E.I)};4 F=H("T");F.M="-";F.U=8(e){6(x>l)x--;E.I=x};4 G=H("T");G.M="+";G.U=8(e){6(x(((m-l)/u)+x))K h;K 1d.1o((v-x)*(h/((m-l)/u)))}g.1x=8(v){6(q)v=q(v);k.1y(v);6(vs)s=v;6(k.L>w)k.1A();c.1a.P=w;c.1g=1;c.17=2;c.Y="V";c.O=p;c.J(0,0,w,20);c.O=o;c.X="1q Z";4 a=t+": "+(k[k.L-1])+" | 1U: "+r+" | 23: "+s;c.W(a,5,15);c.O=n;c.J(0,20,w,y);c.1K=o;18(4 i=0;i1b)?w:1b;h=(h<20)?20:h;4 l=1M 1L();4 n="V";4 o=(Q k==="S"&&k)?"1X":k;4 q="#1I";4 r=1;4 u=h+20;j.7.1H="1G";j.7.1F="#1s";j.7.1c="12 11 "+q;j.7.1D="N";j.7.1C="N";j.7.P=(w+2)+"1B";4 g=H("1a");g.7.1c="12 11 "+q;g.7.1z="N";g.P=w;g.1w=u;4 c=g.1v("2d");4 x=H("1j");x.M="1u: ";x.7.1m="N";4 y=H("1p");y.1i="1r";y.1e=3;y.I=r;y.1h=8(e){r=y.I};4 z=H("T");z.M="-";z.U=8(e){6(r>1)r--;y.I=r};4 A=H("T");A.M="+";A.U=8(e){r++;y.I=1n(r)};9(j,x);9(j,z);9(j,y);9(j,A);9(j,H("1E"));9(j,g);8 1l(p){4 a=1d.1Z(((h-((m.L-1)*2))/m.L));4 s=(p*2)+(p*a);K[s,s+a]}8 1k(i,p){K((l[i]&(1<w)l.1A();c.1a.P=w;c.1g=1;c.17=2;c.Y="V";c.O=q;c.J(0,0,w,20);c.O=o;c.X="1q Z";c.W(t,5,15);c.O=n;c.J(0,20,w,u);c.1K=q;c.1g=1;c.17=0;c.Y="";18(4 p=0;p - - - - - ESP Monitor - - - - -
- - - - -
-
-
-
- - \ No newline at end of file