/** * The MB_FS, filesystems wrapper class v1.0.16 * * This wrapper class is for SD and Flash filesystems interface which supports SdFat (//https://github.com/greiman/SdFat) * * Created June 14, 2023 * * The MIT License (MIT) * Copyright (c) 2023 K. Suwatchai (Mobizt) * * * Permission is hereby granted, free of charge, to any person returning a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MBFS_CLASS_H #define MBFS_CLASS_H #include #include #include "MB_FS_Interfaces.h" #include MB_STRING_INCLUDE_CLASS #define MB_FS_ERROR_FILE_IO_ERROR -300 #define MB_FS_ERROR_FILE_NOT_FOUND -301 #define MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY -302 #define MB_FS_ERROR_SD_STORAGE_IS_NOT_READY -303 #define MB_FS_ERROR_FILE_STILL_OPENED -304 #define mbfs_file_type mb_fs_mem_storage_type #define mbfs_flash mb_fs_mem_storage_type_flash #define mbfs_sd mb_fs_mem_storage_type_sd #define mbfs_undefined mb_fs_mem_storage_type_undefined #define mbfs_type (mbfs_file_type) typedef enum { mb_fs_mem_storage_type_undefined, mb_fs_mem_storage_type_flash, mb_fs_mem_storage_type_sd } mb_fs_mem_storage_type; typedef enum { mb_fs_open_mode_undefined = -1, mb_fs_open_mode_read = 0, mb_fs_open_mode_write, mb_fs_open_mode_append } mb_fs_open_mode; extern FS *ufsp; class MB_FS { public: MB_FS() {} ~MB_FS() {} bool sdBegin(int ss = -1, int sck = -1, int miso = -1, int mosi = -1, uint32_t frequency = 4000000) { mfsp = ufsp; return true; } bool sdSPIBegin(int ss, SPIClass *spiConfig, uint32_t frequency) { mfsp = ufsp; return true; } // Check the mounting status of Flash storage. bool flashReady() { return true; } // Check the mounting status of SD storage. bool sdReady() { return true; } // Check the mounting status of Flash or SD storage with mb_fs_mem_storage_type. bool checkStorageReady(mbfs_file_type type) { return true; } int open(const MB_String &filename, mbfs_file_type type, mb_fs_open_mode mode) { char fmode[8]; switch (mode) { case mb_fs_open_mode_read: strcpy(fmode, "r"); break; case mb_fs_open_mode_write: strcpy(fmode, "w"); break; case mb_fs_open_mode_append: strcpy(fmode, "a"); break; } flash_file = filename; mfsp = ufsp; mb_File = mfsp->open(filename.c_str(), fmode); //Serial.printf(">>> 1 %s, %s, %d ", filename.c_str(), fmode, mb_File); return mb_File; } bool ready(mbfs_file_type type) { return true; } int size(mbfs_file_type type) { return mb_File.size(); } // Check if file is ready to read/write. int available(mbfs_file_type type) { return mb_File.available(); } // Read byte array. Return the number of bytes that completed read or negative value for error. int read(mbfs_file_type type, uint8_t *buf, size_t len) { return mb_File.read(buf, len); } // Print char array. Return the number of bytes that completed write or negative value for error. int print(mbfs_file_type type, const char *str) { return mb_File.print(str); } // Print char array with new line. Return the number of bytes that completed write or negative value for error. int println(mbfs_file_type type, const char *str) { return mb_File.print(str); } // Print integer. Return the number of bytes that completed write or negative value for error. int print(mbfs_file_type type, int v) { return mb_File.print(v); } // Print integer with newline. Return the number of bytes that completed write or negative value for error. int println(mbfs_file_type type, int v) { return mb_File.print(v); } int print(mbfs_file_type type, unsigned int v) { return mb_File.print(v); } // Print integer with newline. Return the number of bytes that completed write or negative value for error. int println(mbfs_file_type type, unsigned int v) { return mb_File.print(v); } // Write byte array. Return the number of bytes that completed write or negative value for error. int write(mbfs_file_type type, uint8_t *buf, size_t len) { return mb_File.write(buf, len); } // Close file. void close(mbfs_file_type type) { mb_File.close(); } // Check file existence. bool existed(const MB_String &filename, mbfs_file_type type) { return mfsp->exists(filename.c_str()); } // Seek to position in file. bool seek(mbfs_file_type type, int pos) { return mb_File.seek(pos); } // Read byte. Return the 1 for completed read or negative value for error. int read(mbfs_file_type type) { return mb_File.read(); } // Write byte. Return the 1 for completed write or negative value for error. int write(mbfs_file_type type, uint8_t v) { return mb_File.write(v); } bool remove(const MB_String &filename, mbfs_file_type type) { return mfsp->remove(filename.c_str()); } fs::File &getFlashFile() { return mb_File; } // Get name of opened file. const char *name(mbfs_file_type type) { return flash_file.c_str(); } // Calculate CRC16 of byte array. uint16_t calCRC(const char *buf) { uint8_t x; uint16_t crc = 0xFFFF; int length = (int)strlen(buf); while (length--) { x = crc >> 8 ^ *buf++; x ^= x >> 4; crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x << 5)) ^ ((uint16_t)x); } return crc; } // Free reserved memory at pointer. void delP(void *ptr) { void **p = (void **)ptr; if (*p) { free(*p); *p = 0; } } // Allocate memory void *newP(size_t len, bool clear = true) { void *p; size_t newLen = getReservedLen(len); #if defined(BOARD_HAS_PSRAM) && defined(MB_STRING_USE_PSRAM) if (ESP.getPsramSize() > 0) p = (void *)ps_malloc(newLen); else p = (void *)malloc(newLen); if (!p) return NULL; #else #if defined(ESP8266_USE_EXTERNAL_HEAP) ESP.setExternalHeap(); #endif p = (void *)malloc(newLen); bool nn = p ? true : false; #if defined(ESP8266_USE_EXTERNAL_HEAP) ESP.resetHeap(); #endif if (!nn) return NULL; #endif if (clear) memset(p, 0, newLen); return p; } size_t getReservedLen(size_t len) { int blen = len + 1; int newlen = (blen / 4) * 4; if (newlen < blen) newlen += 4; return (size_t)newlen; } void createDirs(MB_String dirs, mbfs_file_type type) { if (!longNameSupported()) return; MB_String dir; int count = 0; int lastPos = 0; for (size_t i = 0; i < dirs.length(); i++) { dir.append(1, dirs[i]); count++; if (dirs[i] == '/' && i > 0) { if (dir.length() > 0) { lastPos = dir.length() - 1; #if defined(MBFS_FLASH_FS) if (type == mbfs_flash) MBFS_FLASH_FS.mkdir(dir.substr(0, dir.length() - 1).c_str()); #endif #if defined(MBFS_SD_FS) if (type == mbfs_sd) MBFS_SD_FS.mkdir(dir.substr(0, dir.length() - 1).c_str()); #endif } count = 0; } } if (count > 0) { if (dir.find('.', lastPos) == MB_String::npos) { #if defined(MBFS_FLASH_FS) if (type == mbfs_flash) MBFS_FLASH_FS.mkdir(dir.c_str()); #endif #if defined(MBFS_SD_FS) if (type == mbfs_sd) MBFS_SD_FS.mkdir(dir.c_str()); #endif } } dir.clear(); } bool longNameSupported() { #if defined(MBFS_SDFAT_ENABLED) || defined(MBFS_FLASH_FS) return true; #endif #if defined(MBFS_SD_FS) && (defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO)) return true; #endif return false; } private: uint16_t flash_filename_crc = 0; MB_String flash_file, sd_file; FS *mfsp; File mb_File; }; #endif