diff --git a/doc/html.zip b/doc/html.zip index 20f26f7d..6d6b00ff 100644 Binary files a/doc/html.zip and b/doc/html.zip differ diff --git a/library.properties b/library.properties index a0c2c8e4..f13b4437 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=SdFat -version=2.1.1 +version=2.1.2 license=MIT author=Bill Greiman maintainer=Bill Greiman -sentence=FAT16/FAT32/exFAT file system. -paragraph=FAT16/FAT32/exFAT file system. +sentence=Provides access to SD memory cards. +paragraph=The SdFat library supports FAT16, FAT32, and exFAT file systems on Standard SD, SDHC, and SDXC cards. category=Data Storage url=https://github.com/greiman/SdFat repository=https://github.com/greiman/SdFat.git diff --git a/src/ExFatLib/ExFatConfig.h b/src/ExFatLib/ExFatConfig.h index 5a4e4d15..f04ff756 100644 --- a/src/ExFatLib/ExFatConfig.h +++ b/src/ExFatLib/ExFatConfig.h @@ -26,8 +26,8 @@ #define ExFatConfig_h #include "SdFatConfig.h" -#ifndef READ_ONLY -#define READ_ONLY 0 -#endif // READ_ONLY +#ifndef EXFAT_READ_ONLY +#define EXFAT_READ_ONLY 0 +#endif // EXFAT_READ_ONLY #endif // ExFatConfig_h diff --git a/src/ExFatLib/ExFatFile.cpp b/src/ExFatLib/ExFatFile.cpp index 61e77251..821ac15e 100644 --- a/src/ExFatLib/ExFatFile.cpp +++ b/src/ExFatLib/ExFatFile.cpp @@ -361,13 +361,13 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) { } // Write, truncate, or at end is an error for a directory or read-only file. if ((oflag & (O_TRUNC | O_AT_END)) || (m_flags & FILE_FLAG_WRITE)) { - if (isSubDir() || isReadOnly() || READ_ONLY) { + if (isSubDir() || isReadOnly() || EXFAT_READ_ONLY) { DBG_FAIL_MACRO; goto fail; } } -#if !READ_ONLY +#if !EXFAT_READ_ONLY if (oflag & O_TRUNC) { if (!(m_flags & FILE_FLAG_WRITE)) { DBG_FAIL_MACRO; @@ -381,14 +381,14 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) { DBG_FAIL_MACRO; goto fail; } -#endif // !READ_ONLY +#endif // !EXFAT_READ_ONLY return true; create: -#if READ_ONLY +#if EXFAT_READ_ONLY DBG_FAIL_MACRO; goto fail; -#else // READ_ONLY +#else // EXFAT_READ_ONLY // don't create unless O_CREAT and write if (!(oflag & O_CREAT) || !(modeFlags & FILE_FLAG_WRITE) || !fname) { DBG_WARN_MACRO; @@ -471,7 +471,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) { } } return sync(); -#endif // READ_ONLY +#endif // EXFAT_READ_ONLY fail: // close file diff --git a/src/ExFatLib/ExFatFile.h b/src/ExFatLib/ExFatFile.h index 44a52702..34154a71 100644 --- a/src/ExFatLib/ExFatFile.h +++ b/src/ExFatLib/ExFatFile.h @@ -250,7 +250,7 @@ class ExFatFile { return isOpen() ? m_error & WRITE_ERROR : true; } /** - * Check for BlockDevice busy. + * Check for FsBlockDevice busy. * * \return true if busy else false. */ diff --git a/src/ExFatLib/ExFatFileWrite.cpp b/src/ExFatLib/ExFatFileWrite.cpp index 5e95a7c1..8356f42a 100644 --- a/src/ExFatLib/ExFatFileWrite.cpp +++ b/src/ExFatLib/ExFatFileWrite.cpp @@ -26,7 +26,7 @@ #include "../common/DebugMacros.h" #include "ExFatLib.h" //============================================================================== -#if READ_ONLY +#if EXFAT_READ_ONLY bool ExFatFile::mkdir(ExFatFile* parent, const char* path, bool pFlag) { (void) parent; (void)path; @@ -58,7 +58,7 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) { return false; } //============================================================================== -#else // READ_ONLY +#else // EXFAT_READ_ONLY //------------------------------------------------------------------------------ static uint16_t exFatDirChecksum(const uint8_t* data, uint16_t checksum) { bool skip = data[0] == EXFAT_TYPE_FILE; @@ -753,4 +753,4 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) { m_error |= WRITE_ERROR; return 0; } -#endif // READ_ONLY +#endif // EXFAT_READ_ONLY diff --git a/src/ExFatLib/ExFatFormatter.cpp b/src/ExFatLib/ExFatFormatter.cpp index f124f25f..f424b1f3 100644 --- a/src/ExFatLib/ExFatFormatter.cpp +++ b/src/ExFatLib/ExFatFormatter.cpp @@ -46,7 +46,7 @@ const uint32_t ROOT_CLUSTER = 4; #define writeMsg(pr, str) if (pr) pr->write(str) #endif // PRINT_FORMAT_PROGRESS //------------------------------------------------------------------------------ -bool ExFatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) { +bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) { #if !PRINT_FORMAT_PROGRESS (void)pr; #endif // !PRINT_FORMAT_PROGRESS diff --git a/src/ExFatLib/ExFatFormatter.h b/src/ExFatLib/ExFatFormatter.h index 5c39fcc6..89e81e48 100644 --- a/src/ExFatLib/ExFatFormatter.h +++ b/src/ExFatLib/ExFatFormatter.h @@ -24,7 +24,7 @@ */ #ifndef ExFatFormatter_h #define ExFatFormatter_h -#include "../common/BlockDevice.h" +#include "../common/FsBlockDevice.h" /** * \class ExFatFormatter * \brief Format an exFAT volume. @@ -40,7 +40,7 @@ class ExFatFormatter { * * \return true for success or false for failure. */ - bool format(BlockDevice* dev, uint8_t* secBuf, print_t* pr = nullptr); + bool format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr = nullptr); private: bool syncUpcase(); bool writeUpcase(uint32_t sector); @@ -49,7 +49,7 @@ class ExFatFormatter { uint32_t m_upcaseSector; uint32_t m_upcaseChecksum; uint32_t m_upcaseSize; - BlockDevice* m_dev; + FsBlockDevice* m_dev; uint8_t* m_secBuf; }; #endif // ExFatFormatter_h diff --git a/src/ExFatLib/ExFatName.cpp b/src/ExFatLib/ExFatName.cpp index 479781f5..32c96aff 100644 --- a/src/ExFatLib/ExFatName.cpp +++ b/src/ExFatLib/ExFatName.cpp @@ -83,9 +83,13 @@ size_t ExFatFile::getName7(char* name, size_t count) { } for (uint8_t in = 0; in < 15; in++) { uint16_t c = getLe16(dn->unicode + 2*in); - if (c == 0 || (n + 1) >= count) { + if (c == 0) { goto done; } + if ((n + 1) >= count) { + DBG_FAIL_MACRO; + goto fail; + } name[n++] = c < 0X7F ? c : '?'; } } @@ -140,8 +144,8 @@ size_t ExFatFile::getName8(char* name, size_t count) { // Save space for zero byte. ptr = FsUtf::cpToMb(cp, str, end - 1); if (!ptr) { - // Truncate name. Could goto fail. - goto done; + DBG_FAIL_MACRO; + goto fail; } str = ptr; } diff --git a/src/ExFatLib/ExFatPartition.cpp b/src/ExFatLib/ExFatPartition.cpp index 1ece1e00..dbb00327 100644 --- a/src/ExFatLib/ExFatPartition.cpp +++ b/src/ExFatLib/ExFatPartition.cpp @@ -266,7 +266,7 @@ uint32_t ExFatPartition::freeClusterCount() { } } //------------------------------------------------------------------------------ -bool ExFatPartition::init(BlockDevice* dev, uint8_t part) { +bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part) { uint32_t volStart = 0; uint8_t* cache; pbs_t* pbs; diff --git a/src/ExFatLib/ExFatPartition.h b/src/ExFatLib/ExFatPartition.h index a821a183..464251ef 100644 --- a/src/ExFatLib/ExFatPartition.h +++ b/src/ExFatLib/ExFatPartition.h @@ -29,10 +29,13 @@ * \brief ExFatPartition include file. */ #include "../common/SysCall.h" -#include "../common/BlockDevice.h" +#include "../common/FsBlockDevice.h" #include "../common/FsCache.h" #include "../common/FsStructs.h" -#include "ExFatConfig.h" +/** Set EXFAT_READ_ONLY non-zero for read only */ +#ifndef EXFAT_READ_ONLY +#define EXFAT_READ_ONLY 0 +#endif // EXFAT_READ_ONLY /** Type for exFAT partition */ const uint8_t FAT_TYPE_EXFAT = 64; @@ -79,6 +82,13 @@ class ExFatPartition { uint32_t clusterCount() const {return m_clusterCount;} /** \return the cluster heap start sector. */ uint32_t clusterHeapStartSector() const {return m_clusterHeapStartSector;} + /** End access to volume + * \return pointer to sector size buffer for format. + */ + uint8_t* end() { + m_fatType = 0; + return cacheClear(); + } /** \return the FAT length in sectors */ uint32_t fatLength() const {return m_fatLength;} /** \return the FAT start sector number. */ @@ -96,9 +106,9 @@ class ExFatPartition { * * \return true for success or false for failure. */ - bool init(BlockDevice* dev, uint8_t part); + bool init(FsBlockDevice* dev, uint8_t part); /** - * Check for BlockDevice busy. + * Check for device busy. * * \return true if busy else false. */ @@ -142,7 +152,7 @@ class ExFatPartition { return m_dataCache.prepare(sector, option); #endif // USE_EXFAT_BITMAP_CACHE } - void cacheInit(BlockDevice* dev) { + void cacheInit(FsBlockDevice* dev) { #if USE_EXFAT_BITMAP_CACHE m_bitmapCache.init(dev); #endif // USE_EXFAT_BITMAP_CACHE @@ -213,7 +223,7 @@ class ExFatPartition { uint32_t m_rootDirectoryCluster; uint32_t m_clusterMask; uint32_t m_bytesPerCluster; - BlockDevice* m_blockDev; + FsBlockDevice* m_blockDev; uint8_t m_fatType = 0; uint8_t m_sectorsPerClusterShift; }; diff --git a/src/ExFatLib/ExFatVolume.h b/src/ExFatLib/ExFatVolume.h index 02771243..3c06dab7 100644 --- a/src/ExFatLib/ExFatVolume.h +++ b/src/ExFatLib/ExFatVolume.h @@ -40,7 +40,7 @@ class ExFatVolume : public ExFatPartition { * \param[in] part partition to initialize. * \return true for success or false for failure. */ - bool begin(BlockDevice* dev, bool setCwv = true, uint8_t part = 1) { + bool begin(FsBlockDevice* dev, bool setCwv = true, uint8_t part = 1) { if (!init(dev, part)) { return false; } diff --git a/src/FatLib/FatFile.h b/src/FatLib/FatFile.h index c0632f33..0415bc7b 100644 --- a/src/FatLib/FatFile.h +++ b/src/FatLib/FatFile.h @@ -377,7 +377,7 @@ class FatFile { return isOpen() ? m_error & WRITE_ERROR : true; } /** - * Check for BlockDevice busy. + * Check for device busy. * * \return true if busy else false. */ @@ -442,14 +442,6 @@ class FatFile { * \return true for success or false for failure. */ bool mkdir(FatFile* dir, const char* path, bool pFlag = true); - /** No longer implemented due to Long File Names. - * - * Use getName(char* name, size_t size). - * \return a pointer to replacement suggestion. - */ -#ifndef DOXYGEN_SHOULD_SKIP_THIS - const char* __attribute__((error("use getName(name, size)"))) name(); -#endif // DOXYGEN_SHOULD_SKIP_THIS /** Open a file in the volume root directory. * * \param[in] vol Volume where the file is located. diff --git a/src/FatLib/FatFileLFN.cpp b/src/FatLib/FatFileLFN.cpp index 644bf2c7..b74b7a73 100644 --- a/src/FatLib/FatFileLFN.cpp +++ b/src/FatLib/FatFileLFN.cpp @@ -232,7 +232,7 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) { const uint8_t FIRST_HASH_SEQ = 2; // min value is 2 uint8_t pos = fname->seqPos; DirFat_t* dir; - uint16_t hex; + uint16_t hex = 0; DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS)); DBG_HALT_IF(fname->sfn[pos] != '~' && fname->sfn[pos + 1] != '1'); @@ -242,7 +242,7 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) { #ifdef USE_LFN_HASH hex = Bernstein(fname->begin, fname->end, seq); #else - hex = micros(); + hex += millis(); #endif if (pos > 3) { // Make space in name for ~HHHH. diff --git a/src/FatLib/FatFileSFN.cpp b/src/FatLib/FatFileSFN.cpp index 73c0139b..b9f1efd6 100644 --- a/src/FatLib/FatFileSFN.cpp +++ b/src/FatLib/FatFileSFN.cpp @@ -37,7 +37,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) { uint8_t checksum; #endif // SFN_OPEN_USES_CHKSUM uint8_t lfnOrd = 0; - uint16_t emptyIndex; + uint16_t emptyIndex = 0; uint16_t index = 0; DirFat_t* dir; DirLfn_t* ldir; @@ -53,7 +53,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) { // At EOF if no error. break; } - if (dir->name[0] == FAT_NAME_FREE || dir->name[0] == FAT_NAME_FREE) { + if (dir->name[0] == FAT_NAME_DELETED || dir->name[0] == FAT_NAME_FREE) { if (!emptyFound) { emptyIndex = index; emptyFound = true; diff --git a/src/FatLib/FatFormatter.cpp b/src/FatLib/FatFormatter.cpp index d4f5b384..343f4348 100644 --- a/src/FatLib/FatFormatter.cpp +++ b/src/FatLib/FatFormatter.cpp @@ -45,7 +45,7 @@ const uint16_t FAT16_ROOT_SECTOR_COUNT = #define writeMsg(str) if (m_pr) m_pr->write(str) #endif // PRINT_FORMAT_PROGRESS //------------------------------------------------------------------------------ -bool FatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) { +bool FatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) { bool rtn; m_dev = dev; m_secBuf = secBuf; diff --git a/src/FatLib/FatFormatter.h b/src/FatLib/FatFormatter.h index 90d7e491..2e7d55d9 100644 --- a/src/FatLib/FatFormatter.h +++ b/src/FatLib/FatFormatter.h @@ -25,7 +25,7 @@ #ifndef FatFormatter_h #define FatFormatter_h #include "../common/SysCall.h" -#include "../common/BlockDevice.h" +#include "../common/FsBlockDevice.h" /** * \class FatFormatter * \brief Format a FAT volume. @@ -41,7 +41,7 @@ class FatFormatter { * * \return true for success or false for failure. */ - bool format(BlockDevice* dev, uint8_t* secBuffer, print_t* pr = nullptr); + bool format(FsBlockDevice* dev, uint8_t* secBuffer, print_t* pr = nullptr); private: bool initFatDir(uint8_t fatType, uint32_t sectorCount); @@ -56,7 +56,7 @@ class FatFormatter { uint32_t m_relativeSectors; uint32_t m_sectorCount; uint32_t m_totalSectors; - BlockDevice* m_dev; + FsBlockDevice* m_dev; print_t* m_pr; uint8_t* m_secBuf; uint16_t m_reservedSectorCount; diff --git a/src/FatLib/FatName.cpp b/src/FatLib/FatName.cpp index d970ab64..8a1205cd 100644 --- a/src/FatLib/FatName.cpp +++ b/src/FatLib/FatName.cpp @@ -52,8 +52,7 @@ size_t FatFile::getName(char* name, size_t size) { size_t FatFile::getName7(char* name, size_t size) { FatFile dir; DirLfn_t* ldir; - char* ptr = name; - char* end = ptr + size; + size_t n = 0; if (!isOpen()) { DBG_FAIL_MACRO; goto fail; @@ -78,15 +77,19 @@ size_t FatFile::getName7(char* name, size_t size) { } for (uint8_t i = 0; i < 13; i++) { uint16_t c = getLfnChar(ldir, i); - if (c == 0 || (ptr + 1) == end) { + if (c == 0) { goto done; } - *ptr++ = c >= 0X7F ? '?' : c; + if ((n + 1) >= size) { + DBG_FAIL_MACRO; + goto fail; + } + name[n++] = c >= 0X7F ? '?' : c; } } done: - *ptr = '\0'; - return ptr - name; + name[n] = 0; + return n; fail: name[0] = '\0'; @@ -147,8 +150,8 @@ size_t FatFile::getName8(char* name, size_t size) { // Save space for zero byte. ptr = FsUtf::cpToMb(cp, str, end - 1); if (!ptr) { - // Truncate name. Could goto fail. - goto done; + DBG_FAIL_MACRO; + goto fail; } str = ptr; } @@ -205,8 +208,9 @@ size_t FatFile::getSFN(char* name, size_t size) { continue; } } - if ((j + 1u) == size) { - break; + if ((j + 1u) >= size) { + DBG_FAIL_MACRO; + goto fail; } name[j++] = c; } diff --git a/src/FatLib/FatPartition.cpp b/src/FatLib/FatPartition.cpp index 3af3e9cc..feb2f38d 100644 --- a/src/FatLib/FatPartition.cpp +++ b/src/FatLib/FatPartition.cpp @@ -390,7 +390,7 @@ int32_t FatPartition::freeClusterCount() { return -1; } //------------------------------------------------------------------------------ -bool FatPartition::init(BlockDevice* dev, uint8_t part) { +bool FatPartition::init(FsBlockDevice* dev, uint8_t part) { uint32_t clusterCount; uint32_t totalSectors; uint32_t volumeStartSector = 0; diff --git a/src/FatLib/FatPartition.h b/src/FatLib/FatPartition.h index 6b3cca82..a9d45d98 100644 --- a/src/FatLib/FatPartition.h +++ b/src/FatLib/FatPartition.h @@ -30,7 +30,7 @@ */ #include #include "../common/SysCall.h" -#include "../common/BlockDevice.h" +#include "../common/FsBlockDevice.h" #include "../common/FsCache.h" #include "../common/FsStructs.h" @@ -107,6 +107,13 @@ class FatPartition { uint32_t dataStartSector() const { return m_dataStartSector; } + /** End access to volume + * \return pointer to sector size buffer for format. + */ + uint8_t* end() { + m_fatType = 0; + return cacheClear(); + } /** \return The number of File Allocation Tables. */ uint8_t fatCount() const { return 2; @@ -126,7 +133,7 @@ class FatPartition { int32_t freeClusterCount(); /** Initialize a FAT partition. * - * \param[in] dev BlockDevice for this partition. + * \param[in] dev FsBlockDevice for this partition. * \param[in] part The partition to be used. Legal values for \a part are * 1-4 to use the corresponding partition on a device formatted with * a MBR, Master Boot Record, or zero if the device is formatted as @@ -134,7 +141,7 @@ class FatPartition { * * \return true for success or false for failure. */ - bool init(BlockDevice* dev, uint8_t part = 1); + bool init(FsBlockDevice* dev, uint8_t part = 1); /** \return The number of entries in the root directory for FAT16 volumes. */ uint16_t rootDirEntryCount() const { return m_rootDirEntryCount; @@ -158,7 +165,7 @@ class FatPartition { return fatGet(n, v); } /** - * Check for BlockDevice busy. + * Check for FsBlockDevice busy. * * \return true if busy else false. */ @@ -179,7 +186,7 @@ class FatPartition { static const uint16_t m_bytesPerSector = 1 << m_bytesPerSectorShift; static const uint16_t m_sectorMask = m_bytesPerSector - 1; //---------------------------------------------------------------------------- - BlockDevice* m_blockDev; // sector device + FsBlockDevice* m_blockDev; // sector device uint8_t m_sectorsPerCluster; // Cluster size in sectors. uint8_t m_clusterSectorMask; // Mask to extract sector of cluster. uint8_t m_sectorsPerClusterShift; // Cluster count to sector count shift. diff --git a/src/FatLib/FatVolume.h b/src/FatLib/FatVolume.h index dbf3574a..fe79a42a 100644 --- a/src/FatLib/FatVolume.h +++ b/src/FatLib/FatVolume.h @@ -43,7 +43,7 @@ class FatVolume : public FatPartition { * \param[in] part partition to initialize. * \return true for success or false for failure. */ - bool begin(BlockDevice* dev, bool setCwv = true, uint8_t part = 1) { + bool begin(FsBlockDevice* dev, bool setCwv = true, uint8_t part = 1) { if (!init(dev, part)) { return false; } @@ -72,7 +72,6 @@ class FatVolume : public FatPartition { * \return true for success or false for failure. */ bool chdir(const char *path); - //---------------------------------------------------------------------------- /** * Test for the existence of a file. diff --git a/src/FsLib/FsFile.h b/src/FsLib/FsFile.h index a0d2a8f9..313abb3e 100644 --- a/src/FsLib/FsFile.h +++ b/src/FsLib/FsFile.h @@ -239,7 +239,7 @@ class FsBaseFile { m_xFile ? m_xFile->getWriteError() : true; } /** - * Check for BlockDevice busy. + * Check for FsBlockDevice busy. * * \return true if busy else false. */ @@ -355,14 +355,6 @@ class FsBaseFile { * \return true for success or false for failure. */ bool mkdir(FsBaseFile* dir, const char* path, bool pFlag = true); - /** No longer implemented due to Long File Names. - * - * Use getName(char* name, size_t size). - * \return a pointer to replacement suggestion. - */ -#ifndef DOXYGEN_SHOULD_SKIP_THIS - const char* __attribute__((error("use getName(name, size)"))) name(); -#endif // DOXYGEN_SHOULD_SKIP_THIS /** Open a file or directory by name. * * \param[in] dir An open file instance for the directory containing @@ -761,6 +753,14 @@ class FsBaseFile { return m_fFile ? length < (1ULL << 32) && m_fFile->truncate(length) : m_xFile ? m_xFile->truncate(length) : false; } + /** Write a string to a file. Used by the Arduino Print class. + * \param[in] str Pointer to the string. + * Use getWriteError to check for errors. + * \return count of characters written for success or -1 for failure. + */ + size_t write(const char* str) { + return write(str, strlen(str)); + } /** Write a byte to a file. Required by the Arduino Print class. * \param[in] b the byte to be written. * Use getWriteError to check for errors. diff --git a/src/FsLib/FsFormatter.h b/src/FsLib/FsFormatter.h new file mode 100644 index 00000000..0c5d3a0a --- /dev/null +++ b/src/FsLib/FsFormatter.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2011-2021 Bill Greiman + * This file is part of the SdFat library for SD memory cards. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining 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 FsFormatter_h +#define FsFormatter_h +#include "FatLib/FatLib.h" +#include "ExFatLib/ExFatLib.h" +/** + * \class FsFormatter + * \brief Format a exFAT/FAT volume. + */ +class FsFormatter { + public: + /** + * Format a FAT volume. + * + * \param[in] dev Block device for volume. + * \param[in] secBuffer buffer for writing to volume. + * \param[in] pr Print device for progress output. + * + * \return true for success or false for failure. + */ + bool format(FsBlockDevice* dev, uint8_t* secBuffer, print_t* pr = nullptr) { + uint32_t sectorCount = dev->sectorCount(); + if (sectorCount == 0) { + return false; + } + return sectorCount <= 67108864 ? + m_fFmt.format(dev, secBuffer, pr) : + m_xFmt.format(dev, secBuffer, pr); + } + private: + FatFormatter m_fFmt; + ExFatFormatter m_xFmt; +}; +#endif // FsFormatter_h diff --git a/src/FsLib/FsLib.h b/src/FsLib/FsLib.h index 97ff9866..2539797a 100644 --- a/src/FsLib/FsLib.h +++ b/src/FsLib/FsLib.h @@ -30,4 +30,5 @@ */ #include "FsVolume.h" #include "FsFile.h" +#include "FsFormatter.h" #endif // FsLib_h diff --git a/src/FsLib/FsVolume.cpp b/src/FsLib/FsVolume.cpp index 841a9c7b..e36d6ce6 100644 --- a/src/FsLib/FsVolume.cpp +++ b/src/FsLib/FsVolume.cpp @@ -25,16 +25,16 @@ #include "FsLib.h" FsVolume* FsVolume::m_cwv = nullptr; //------------------------------------------------------------------------------ -bool FsVolume::begin(BlockDevice* blockDev) { +bool FsVolume::begin(FsBlockDevice* blockDev, bool setCwv, uint8_t part) { m_blockDev = blockDev; m_fVol = nullptr; m_xVol = new (m_volMem) ExFatVolume; - if (m_xVol && m_xVol->begin(m_blockDev, false)) { + if (m_xVol && m_xVol->begin(m_blockDev, false, part)) { goto done; } m_xVol = nullptr; m_fVol = new (m_volMem) FatVolume; - if (m_fVol && m_fVol->begin(m_blockDev, false)) { + if (m_fVol && m_fVol->begin(m_blockDev, false, part)) { goto done; } m_cwv = nullptr; @@ -42,7 +42,9 @@ bool FsVolume::begin(BlockDevice* blockDev) { return false; done: - m_cwv = this; + if (setCwv || !m_cwv) { + m_cwv = this; + } return true; } //------------------------------------------------------------------------------ diff --git a/src/FsLib/FsVolume.h b/src/FsLib/FsVolume.h index ad3e7b48..ec344b35 100644 --- a/src/FsLib/FsVolume.h +++ b/src/FsLib/FsVolume.h @@ -46,9 +46,11 @@ class FsVolume { /** * Initialize an FatVolume object. * \param[in] blockDev Device block driver. + * \param[in] setCwv Set current working volume if true. + * \param[in] part partition to initialize. * \return true for success or false for failure. */ - bool begin(BlockDevice* blockDev); + bool begin(FsBlockDevice* blockDev, bool setCwv = true, uint8_t part = 1); #ifndef DOXYGEN_SHOULD_SKIP_THIS uint32_t __attribute__((error("use sectorsPerCluster()"))) blocksPerCluster(); #endif // DOXYGEN_SHOULD_SKIP_THIS @@ -86,10 +88,14 @@ class FsVolume { return m_fVol ? m_fVol->dataStartSector() : m_xVol ? m_xVol->clusterHeapStartSector() : 0; } - /** free dynamic memory and end access to volume */ - void end() { + /** End access to volume + * \return pointer to sector size buffer for format. + */ + uint8_t* end() { m_fVol = nullptr; m_xVol = nullptr; + static_assert(sizeof(m_volMem) >= 512, "m_volMem too small"); + return reinterpret_cast(m_volMem); } /** Test for the existence of a file in a directory * @@ -119,7 +125,7 @@ class FsVolume { m_xVol ? m_xVol->freeClusterCount() : 0; } /** - * Check for BlockDevice busy. + * Check for device busy. * * \return true if busy else false. */ @@ -379,6 +385,6 @@ class FsVolume { static FsVolume* m_cwv; FatVolume* m_fVol = nullptr; ExFatVolume* m_xVol = nullptr; - BlockDevice* m_blockDev; + FsBlockDevice* m_blockDev; }; #endif // FsVolume_h diff --git a/src/SdCard/SdCardInterface.h b/src/SdCard/SdCardInterface.h index 0d81e937..11161036 100644 --- a/src/SdCard/SdCardInterface.h +++ b/src/SdCard/SdCardInterface.h @@ -24,14 +24,16 @@ */ #ifndef SdCardInterface_h #define SdCardInterface_h -#include "../common/BlockDeviceInterface.h" +#include "../common/FsBlockDeviceInterface.h" #include "SdCardInfo.h" /** * \class SdCardInterface * \brief Abstract interface for an SD card. */ -class SdCardInterface : public BlockDeviceInterface { +class SdCardInterface : public FsBlockDeviceInterface { public: + /** end use of card */ + virtual void end() = 0; /** Erase a range of sectors. * * \param[in] firstSector The address of the first sector in the range. @@ -46,6 +48,18 @@ class SdCardInterface : public BlockDeviceInterface { virtual uint32_t errorData() const = 0; /** \return true if card is busy. */ virtual bool isBusy() = 0; + /** \return false by default */ + virtual bool hasDedicatedSpi() {return false;} + /** \return false by default */ + bool virtual isDedicatedSpi() {return false;} + /** Set SPI sharing state + * \param[in] value desired state. + * \return false by default. + */ + virtual bool setDedicatedSpi(bool value) { + (void)value; + return false; + } /** * Read a card's CID register. * diff --git a/src/SdCard/SdSpiCard.cpp b/src/SdCard/SdSpiCard.cpp index 158427c2..b2afef16 100644 --- a/src/SdCard/SdSpiCard.cpp +++ b/src/SdCard/SdSpiCard.cpp @@ -665,7 +665,7 @@ bool DedicatedSpiCard::begin(SdSpiConfig spiConfig) { if (!SharedSpiCard::begin(spiConfig)) { return false; } - m_sharedSpi = spiOptionShared(spiConfig.options); + m_dedicatedSpi = spiOptionDedicated(spiConfig.options); return true; } //------------------------------------------------------------------------------ @@ -687,18 +687,25 @@ bool DedicatedSpiCard::readSectors( } } m_curSector += ns; - return m_sharedSpi ? readStop() : true; + return m_dedicatedSpi ? true : readStop(); fail: return false; } //------------------------------------------------------------------------------ +bool DedicatedSpiCard::setDedicatedSpi(bool value) { + if (!syncDevice()) { + return false; + } + m_dedicatedSpi = value; + return true; +} +//------------------------------------------------------------------------------ bool DedicatedSpiCard::writeSector(uint32_t sector, const uint8_t* src) { - if (m_sharedSpi) { - return SharedSpiCard::writeSector(sector, src); - } else { + if (m_dedicatedSpi) { return writeSectors(sector, src, 1); } + return SharedSpiCard::writeSector(sector, src); } //------------------------------------------------------------------------------ bool DedicatedSpiCard::writeSectors( @@ -715,7 +722,7 @@ bool DedicatedSpiCard::writeSectors( } } m_curSector += ns; - return m_sharedSpi ? writeStop() : true; + return m_dedicatedSpi ? true : writeStop(); fail: return false; diff --git a/src/SdCard/SdSpiCard.h b/src/SdCard/SdSpiCard.h index c4848afc..d0b5b7bd 100644 --- a/src/SdCard/SdSpiCard.h +++ b/src/SdCard/SdSpiCard.h @@ -41,7 +41,7 @@ #if HAS_SDIO_CLASS class SharedSpiCard : public SdCardInterface { #elif USE_BLOCK_DEVICE_INTERFACE -class SharedSpiCard : public BlockDeviceInterface { +class SharedSpiCard : public FsBlockDeviceInterface { #else // HAS_SDIO_CLASS class SharedSpiCard { #endif // HAS_SDIO_CLASS @@ -59,6 +59,10 @@ class SharedSpiCard { * \return true for success or false for failure. */ bool begin(SdSpiConfig spiConfig); + /** End use of card */ + void end() { + spiEnd(); + } /** Erase a range of sectors. * * \param[in] firstSector The address of the first sector in the range. @@ -96,12 +100,16 @@ class SharedSpiCard { uint32_t errorData() const { return m_status; } + /** \return false for shared class. */ + bool hasDedicatedSpi() {return false;} /** * Check for busy. MISO low indicates the card is busy. * * \return true if busy else false. */ bool isBusy(); + /** \return false, can't be in dedicated state. */ + bool isDedicatedSpi() {return false;} /** * Read a card's CID register. The CID contains card identification * information such as Manufacturer ID, Product name, Product serial @@ -189,6 +197,14 @@ class SharedSpiCard { // Use sectorCount(). cardSize() will be removed in the future. uint32_t __attribute__((error("use sectorCount()"))) cardSize(); #endif // DOXYGEN_SHOULD_SKIP_THIS + /** Set SPI sharing state + * \param[in] value desired state. + * \return false for shared card + */ + bool setDedicatedSpi(bool value) { + (void)value; + return false; + } /** end a mult-sector transfer. * * \return true for success or false for failure. @@ -263,7 +279,6 @@ class SharedSpiCard { } bool waitReady(uint16_t ms); bool writeData(uint8_t token, const uint8_t* src); - #if SPI_DRIVER_SELECT < 2 void spiActivate() { m_spiDriver.activate(); @@ -274,6 +289,9 @@ class SharedSpiCard { void spiDeactivate() { m_spiDriver.deactivate(); } + void spiEnd() { + m_spiDriver.end(); + } uint8_t spiReceive() { return m_spiDriver.receive(); } @@ -300,6 +318,9 @@ class SharedSpiCard { void spiDeactivate() { m_spiDriverPtr->deactivate(); } + void spiEnd() { + m_spiDriverPtr->end(); + } uint8_t spiReceive() { return m_spiDriverPtr->receive(); } @@ -317,7 +338,6 @@ class SharedSpiCard { } SdSpiDriver* m_spiDriverPtr; #endif // SPI_DRIVER_SELECT < 2 - SdCsPin_t m_csPin; uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED; bool m_spiActive; @@ -340,6 +360,10 @@ class DedicatedSpiCard : public SharedSpiCard { * \return true for success or false for failure. */ bool begin(SdSpiConfig spiConfig); + /** \return true, can be in dedicaded state. */ + bool hasDedicatedSpi() {return true;} + /** \return true if in dedicated SPI state. */ + bool isDedicatedSpi() {return m_dedicatedSpi;} /** * Read a 512 byte sector from an SD card. * @@ -357,6 +381,11 @@ class DedicatedSpiCard : public SharedSpiCard { * \return true for success or false for failure. */ bool readSectors(uint32_t sector, uint8_t* dst, size_t ns); + /** Set SPI sharing state + * \param[in] value desired state. + * \return true for success else false; + */ + bool setDedicatedSpi(bool value); /** * Write a 512 byte sector to an SD card. * @@ -377,7 +406,7 @@ class DedicatedSpiCard : public SharedSpiCard { private: uint32_t m_curSector; - bool m_sharedSpi = true; + bool m_dedicatedSpi = false; }; //============================================================================== #if ENABLE_DEDICATED_SPI diff --git a/src/SdCard/SdioCard.h b/src/SdCard/SdioCard.h index 9b3ef9cc..cfbe4cdc 100644 --- a/src/SdCard/SdioCard.h +++ b/src/SdCard/SdioCard.h @@ -61,9 +61,9 @@ class SdioCard : public SdCardInterface { */ bool begin(SdioConfig sdioConfig); /** Disable an SDIO card. - * \return false - not implemented. + * not implemented. */ - bool end() {return false;} + void end() {} #ifndef DOXYGEN_SHOULD_SKIP_THIS uint32_t __attribute__((error("use sectorCount()"))) cardSize(); diff --git a/src/SdCard/SdioTeensy.cpp b/src/SdCard/SdioTeensy.cpp index a938d7e3..8908919c 100644 --- a/src/SdCard/SdioTeensy.cpp +++ b/src/SdCard/SdioTeensy.cpp @@ -572,7 +572,6 @@ static bool transferStop() { if (!cardCommand(CMD12_XFERTYP, 0)) { return sdError(SD_CARD_ERROR_CMD12); } -// if (yieldTimeout(isBusyCMD13)) { if (yieldTimeout(isBusyDat)) { return sdError(SD_CARD_ERROR_CMD13); } @@ -599,7 +598,7 @@ static bool yieldTimeout(bool (*fcn)()) { m_busyFcn = 0; return true; } - SysCall::yield(); + yield(); } m_busyFcn = 0; return false; // Caller will set errorCode. diff --git a/src/SdFat.h b/src/SdFat.h index 0530f24e..ac70377b 100644 --- a/src/SdFat.h +++ b/src/SdFat.h @@ -38,15 +38,15 @@ #endif // INCLUDE_SDIOS //------------------------------------------------------------------------------ /** SdFat version for cpp use. */ -#define SD_FAT_VERSION 20101 +#define SD_FAT_VERSION 20102 /** SdFat version as string. */ -#define SD_FAT_VERSION_STR "2.1.1" +#define SD_FAT_VERSION_STR "2.1.2" //============================================================================== /** * \class SdBase * \brief base SD file system template class. */ -template +template class SdBase : public Vol { public: //---------------------------------------------------------------------------- @@ -115,6 +115,14 @@ class SdBase : public Vol { return m_card && !m_card->errorCode(); } //---------------------------------------------------------------------------- + /** End use of card. */ + void end() { + Vol::end(); + if (m_card) { + m_card->end(); + } + } + //---------------------------------------------------------------------------- /** %Print error info and halt. * * \param[in] pr Print destination. @@ -128,7 +136,7 @@ class SdBase : public Vol { } else if (!Vol::fatType()) { pr->println(F("Check SD format.")); } - SysCall::halt(); + while (true) {} } //---------------------------------------------------------------------------- /** %Print error info and halt. @@ -153,13 +161,51 @@ class SdBase : public Vol { errorHalt(pr); } //---------------------------------------------------------------------------- + /** Format SD card + * + * \param[in] pr Print destination. + * \return true for success else false. + */ + bool format(print_t* pr = nullptr) { + Fmt fmt; + uint8_t* mem = Vol::end(); + if (!mem) { + return false; + } + bool switchSpi = hasDedicatedSpi() && !isDedicatedSpi(); + if (switchSpi && !setDedicatedSpi(true)) { + return 0; + } + bool rtn = fmt.format(card(), mem, pr); + if (switchSpi && !setDedicatedSpi(false)) { + return 0; + } + return rtn; + } + //---------------------------------------------------------------------------- + /** \return the free cluster count. */ + uint32_t freeClusterCount() { + bool switchSpi = hasDedicatedSpi() && !isDedicatedSpi(); + if (switchSpi && !setDedicatedSpi(true)) { + return 0; + } + uint32_t rtn = Vol::freeClusterCount(); + if (switchSpi && !setDedicatedSpi(false)) { + return 0; + } + return rtn; + } + //---------------------------------------------------------------------------- + /** \return true if can be in dedicated SPI state */ + bool hasDedicatedSpi() {return m_card ? m_card->hasDedicatedSpi() : false;} + //---------------------------------------------------------------------------- /** %Print error info and halt. * * \param[in] pr Print destination. */ void initErrorHalt(print_t* pr) { initErrorPrint(pr); - SysCall::halt(); + while (true) {} } //---------------------------------------------------------------------------- /** %Print error info and halt. @@ -177,7 +223,7 @@ class SdBase : public Vol { * \param[in] pr Print destination. * \param[in] msg Message to print. */ - void initErrorHalt(Print* pr, const __FlashStringHelper* msg) { + void initErrorHalt(print_t* pr, const __FlashStringHelper* msg) { pr->println(msg); initErrorHalt(pr); } @@ -186,7 +232,7 @@ class SdBase : public Vol { * * \param[in] pr Print destination. */ - void initErrorPrint(Print* pr) { + void initErrorPrint(print_t* pr) { pr->println(F("begin() failed")); if (sdErrorCode()) { pr->println(F("Do not reformat the SD.")); @@ -197,6 +243,9 @@ class SdBase : public Vol { errorPrint(pr); } //---------------------------------------------------------------------------- + /** \return true if in dedicated SPI state. */ + bool isDedicatedSpi() {return m_card ? m_card->isDedicatedSpi() : false;} + //---------------------------------------------------------------------------- /** %Print volume FAT/exFAT type. * * \param[in] pr Print destination. @@ -241,7 +290,7 @@ class SdBase : public Vol { * \param[in] pr Print destination. * \param[in] msg Message to print. */ - void errorPrint(Print* pr, const __FlashStringHelper* msg) { + void errorPrint(print_t* pr, const __FlashStringHelper* msg) { pr->print(F("error: ")); pr->println(msg); errorPrint(pr); @@ -278,6 +327,17 @@ class SdBase : public Vol { /** \return SD card error data. */ uint8_t sdErrorData() {return m_card ? m_card->errorData() : 0;} //---------------------------------------------------------------------------- + /** Set SPI sharing state + * \param[in] value desired state. + * \return true for success else false; + */ + bool setDedicatedSpi(bool value) { + if (m_card) { + return m_card->setDedicatedSpi(value); + } + return false; + } + //---------------------------------------------------------------------------- /** \return pointer to base volume */ Vol* vol() {return reinterpret_cast(this);} //---------------------------------------------------------------------------- @@ -341,7 +401,7 @@ class SdBase : public Vol { #endif // ENABLE_ARDUINO_SERIAL //---------------------------------------------------------------------------- private: - SdCard* m_card; + SdCard* m_card = nullptr; SdCardFactory m_cardFactory; }; //------------------------------------------------------------------------------ @@ -349,73 +409,27 @@ class SdBase : public Vol { * \class SdFat32 * \brief SD file system class for FAT volumes. */ -class SdFat32 : public SdBase { +class SdFat32 : public SdBase { public: - /** Format a SD card FAT32/FAT16. - * - * \param[in] pr Optional Print information. - * \return true for success or false for failure. - */ - bool format(print_t* pr = nullptr) { - FatFormatter fmt; - uint8_t* cache = cacheClear(); - if (!cache) { - return false; - } - return fmt.format(card(), cache, pr); - } }; //------------------------------------------------------------------------------ /** * \class SdExFat * \brief SD file system class for exFAT volumes. */ -class SdExFat : public SdBase { +class SdExFat : public SdBase { public: - /** Format a SD card exFAT. - * - * \param[in] pr Optional Print information. - * \return true for success or false for failure. - */ - bool format(print_t* pr = nullptr) { - ExFatFormatter fmt; - uint8_t* cache = cacheClear(); - if (!cache) { - return false; - } - return fmt.format(card(), cache, pr); - } }; //------------------------------------------------------------------------------ /** * \class SdFs * \brief SD file system class for FAT16, FAT32, and exFAT volumes. */ -class SdFs : public SdBase { +class SdFs : public SdBase { public: - /** Format a SD card FAT or exFAT. - * - * \param[in] pr Optional Print information. - * \return true for success or false for failure. - */ - bool format(print_t* pr = nullptr) { - static_assert(sizeof(m_volMem) >= 512, "m_volMem too small"); - uint32_t sectorCount = card()->sectorCount(); - if (sectorCount == 0) { - return false; - } - end(); - if (sectorCount > 67108864) { - ExFatFormatter fmt; - return fmt.format(card(), reinterpret_cast(m_volMem), pr); - } else { - FatFormatter fmt; - return fmt.format(card(), reinterpret_cast(m_volMem), pr); - } - } }; //------------------------------------------------------------------------------ -#if SDFAT_FILE_TYPE == 1 +#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN) /** Select type for SdFat. */ typedef SdFat32 SdFat; /** Select type for SdBaseFile. */ @@ -435,11 +449,11 @@ typedef FsBaseFile SdBaseFile; #if defined __has_include #if __has_include() #define HAS_INCLUDE_FS_H -#warning File not defined because __has__include(FS.h) +#warning File not defined because __has_include(FS.h) #endif // __has_include() #endif // defined __has_include #ifndef HAS_INCLUDE_FS_H -#if SDFAT_FILE_TYPE == 1 +#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN) /** Select type for File. */ typedef File32 File; #elif SDFAT_FILE_TYPE == 2 diff --git a/src/SdFatConfig.h b/src/SdFatConfig.h index e148910d..141ffd9e 100644 --- a/src/SdFatConfig.h +++ b/src/SdFatConfig.h @@ -137,10 +137,10 @@ #endif // SD_MAX_INIT_RATE_KHZ /** * Set USE_BLOCK_DEVICE_INTERFACE nonzero to use a generic block device. - * This allow use of an external BlockDevice driver that is derived from - * the BlockDeviceInterface like this: + * This allow use of an external FsBlockDevice driver that is derived from + * the FsBlockDeviceInterface like this: * - * class UsbMscDriver : public BlockDeviceInterface { + * class UsbMscDriver : public FsBlockDeviceInterface { * ... code for USB mass storage class driver. * }; * @@ -341,19 +341,6 @@ typedef uint8_t SdCsPin_t; #define ENDL_CALLS_FLUSH 0 #endif // ENDL_CALLS_FLUSH //------------------------------------------------------------------------------ -/** - * Handle Watchdog Timer for WiFi modules. - * - * Yield will be called before accessing the SPI bus if it has been more - * than WDT_YIELD_TIME_MILLIS milliseconds since the last yield call by SdFat. - */ -#if defined(PLATFORM_ID) || defined(ESP8266) -// If Particle device or ESP8266 call yield. -#define WDT_YIELD_TIME_MILLIS 100 -#else // defined(PLATFORM_ID) || defined(ESP8266) -#define WDT_YIELD_TIME_MILLIS 0 -#endif // defined(PLATFORM_ID) || defined(ESP8266) -//------------------------------------------------------------------------------ /** * Set USE_SIMPLE_LITTLE_ENDIAN nonzero for little endian processors * with no memory alignment restrictions. diff --git a/src/SpiDriver/SdSpiArtemis.cpp b/src/SpiDriver/SdSpiArtemis.cpp index 4b0a56a6..a7a064f7 100644 --- a/src/SpiDriver/SdSpiArtemis.cpp +++ b/src/SpiDriver/SdSpiArtemis.cpp @@ -42,6 +42,10 @@ void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::end() { + m_spi->end(); +} +//------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } diff --git a/src/SpiDriver/SdSpiAvr.h b/src/SpiDriver/SdSpiAvr.h index 8d02fbf9..c3df3fe8 100644 --- a/src/SpiDriver/SdSpiAvr.h +++ b/src/SpiDriver/SdSpiAvr.h @@ -27,19 +27,23 @@ // Use of in-line for AVR to save flash. #define nop asm volatile ("nop\n\t") //------------------------------------------------------------------------------ +inline void SdSpiArduinoDriver::activate() { + SPI.beginTransaction(m_spiSettings); +} +//------------------------------------------------------------------------------ inline void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { (void)spiConfig; SPI.begin(); } //------------------------------------------------------------------------------ -inline void SdSpiArduinoDriver::activate() { - SPI.beginTransaction(m_spiSettings); -} -//------------------------------------------------------------------------------ inline void SdSpiArduinoDriver::deactivate() { SPI.endTransaction(); } //------------------------------------------------------------------------------ +inline void SdSpiArduinoDriver::end() { + SPI.end(); +} +//------------------------------------------------------------------------------ inline uint8_t SdSpiArduinoDriver::receive() { return SPI.transfer(0XFF); } diff --git a/src/SpiDriver/SdSpiBareUnoDriver.h b/src/SpiDriver/SdSpiBareUnoDriver.h index 25a03214..c0c8bbdd 100644 --- a/src/SpiDriver/SdSpiBareUnoDriver.h +++ b/src/SpiDriver/SdSpiBareUnoDriver.h @@ -92,10 +92,6 @@ class SdSpiDriverBareUno { public: /** Activate SPI hardware. */ void activate() {} - /** deactivate SPI driver. */ - void end() {} - /** Deactivate SPI hardware. */ - void deactivate() {} /** Initialize the SPI bus. * * \param[in] spiConfig SD card configuration. @@ -112,6 +108,10 @@ class SdSpiDriverBareUno { unoPinMode(UNO_SCK, OUTPUT); unoPinMode(UNO_MOSI, OUTPUT); } + /** Deactivate SPI hardware. */ + void deactivate() {} + /** deactivate SPI driver. */ + void end() {} /** Receive a byte. * * \return The byte. diff --git a/src/SpiDriver/SdSpiBaseClass.h b/src/SpiDriver/SdSpiBaseClass.h index 5acca7a0..cd61fef7 100644 --- a/src/SpiDriver/SdSpiBaseClass.h +++ b/src/SpiDriver/SdSpiBaseClass.h @@ -43,6 +43,8 @@ class SdSpiBaseClass { virtual void begin(SdSpiConfig config) = 0; /** Deactivate SPI hardware. */ virtual void deactivate() {} + /** deactivate SPI driver. */ + virtual void end() {} /** Receive a byte. * * \return The byte. diff --git a/src/SpiDriver/SdSpiDriver.h b/src/SpiDriver/SdSpiDriver.h index deb4220c..dfbad17f 100644 --- a/src/SpiDriver/SdSpiDriver.h +++ b/src/SpiDriver/SdSpiDriver.h @@ -50,16 +50,15 @@ const uint8_t SHARED_SPI = 0; const uint8_t DEDICATED_SPI = 1; /** * \param[in] opt option field of SdSpiConfig. - * \return true for shared SPI. + * \return true for dedicated SPI. */ -inline bool spiOptionShared(uint8_t opt) {return !(opt & DEDICATED_SPI);} - +inline bool spiOptionDedicated(uint8_t opt) {return opt & DEDICATED_SPI;} #else // ENABLE_DEDICATED_SPI /** * \param[in] opt option field of SdSpiConfig. - * \return true for shared SPI. + * \return true for dedicated SPI. */ -inline bool spiOptionShared(uint8_t opt) {(void)opt; return true;} +inline bool spiOptionDedicated(uint8_t opt) {(void)opt; return false;} #endif // ENABLE_DEDICATED_SPI //------------------------------------------------------------------------------ /** SPISettings for SCK frequency in Hz. */ diff --git a/src/SpiDriver/SdSpiDue.cpp b/src/SpiDriver/SdSpiDue.cpp index cfb6e7e1..f9260b11 100644 --- a/src/SpiDriver/SdSpiDue.cpp +++ b/src/SpiDriver/SdSpiDue.cpp @@ -62,25 +62,6 @@ static bool dmac_channel_transfer_done(uint32_t ul_num) { return (DMAC->DMAC_CHSR & (DMAC_CHSR_ENA0 << ul_num)) ? false : true; } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { - (void)spiConfig; - SPI.begin(); -#if USE_SAM3X_DMAC - pmc_enable_periph_clk(ID_DMAC); - dmac_disable(); - DMAC->DMAC_GCFG = DMAC_GCFG_ARB_CFG_FIXED; - dmac_enable(); -#if USE_SAM3X_BUS_MATRIX_FIX - MATRIX->MATRIX_WPMR = 0x4d415400; - MATRIX->MATRIX_MCFG[1] = 1; - MATRIX->MATRIX_MCFG[2] = 1; - MATRIX->MATRIX_SCFG[0] = 0x01000010; - MATRIX->MATRIX_SCFG[1] = 0x01000010; - MATRIX->MATRIX_SCFG[7] = 0x01000010; -#endif // USE_SAM3X_BUS_MATRIX_FIX -#endif // USE_SAM3X_DMAC -} -//------------------------------------------------------------------------------ // start RX DMA static void spiDmaRX(uint8_t* dst, uint16_t count) { dmac_channel_disable(SPI_DMAC_RX_CH); @@ -141,10 +122,33 @@ void SdSpiArduinoDriver::activate() { pSpi->SPI_CR |= SPI_CR_SPIEN; } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { + (void)spiConfig; + SPI.begin(); +#if USE_SAM3X_DMAC + pmc_enable_periph_clk(ID_DMAC); + dmac_disable(); + DMAC->DMAC_GCFG = DMAC_GCFG_ARB_CFG_FIXED; + dmac_enable(); +#if USE_SAM3X_BUS_MATRIX_FIX + MATRIX->MATRIX_WPMR = 0x4d415400; + MATRIX->MATRIX_MCFG[1] = 1; + MATRIX->MATRIX_MCFG[2] = 1; + MATRIX->MATRIX_SCFG[0] = 0x01000010; + MATRIX->MATRIX_SCFG[1] = 0x01000010; + MATRIX->MATRIX_SCFG[7] = 0x01000010; +#endif // USE_SAM3X_BUS_MATRIX_FIX +#endif // USE_SAM3X_DMAC +} +//------------------------------------------------------------------------------ void SdSpiArduinoDriver::deactivate() { SPI.endTransaction(); } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::end() { + SPI.end(); +} +//------------------------------------------------------------------------------ static inline uint8_t spiTransfer(uint8_t b) { Spi* pSpi = SPI0; diff --git a/src/SpiDriver/SdSpiESP.cpp b/src/SpiDriver/SdSpiESP.cpp index 8e20155b..bc58f5d3 100644 --- a/src/SpiDriver/SdSpiESP.cpp +++ b/src/SpiDriver/SdSpiESP.cpp @@ -48,6 +48,10 @@ void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::end() { + m_spi->end(); +} +//------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } diff --git a/src/SpiDriver/SdSpiLibDriver.h b/src/SpiDriver/SdSpiLibDriver.h index 519132ee..0522419c 100644 --- a/src/SpiDriver/SdSpiLibDriver.h +++ b/src/SpiDriver/SdSpiLibDriver.h @@ -46,6 +46,10 @@ inline void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) { m_spi->begin(); } //------------------------------------------------------------------------------ +inline void SdSpiArduinoDriver::end() { + m_spi->end(); +} +//------------------------------------------------------------------------------ inline void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } diff --git a/src/SpiDriver/SdSpiParticle.cpp b/src/SpiDriver/SdSpiParticle.cpp index 69192a10..e6918204 100644 --- a/src/SpiDriver/SdSpiParticle.cpp +++ b/src/SpiDriver/SdSpiParticle.cpp @@ -47,6 +47,10 @@ void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::end() { + m_spi->end(); +} +//------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } diff --git a/src/SpiDriver/SdSpiSTM32.cpp b/src/SpiDriver/SdSpiSTM32.cpp index 4d2c758f..1e2369ac 100644 --- a/src/SpiDriver/SdSpiSTM32.cpp +++ b/src/SpiDriver/SdSpiSTM32.cpp @@ -51,6 +51,10 @@ void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::end() { + m_spi->end(); +} +//------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } diff --git a/src/SpiDriver/SdSpiSTM32Core.cpp b/src/SpiDriver/SdSpiSTM32Core.cpp index 4de78691..86b2a7a0 100644 --- a/src/SpiDriver/SdSpiSTM32Core.cpp +++ b/src/SpiDriver/SdSpiSTM32Core.cpp @@ -43,6 +43,10 @@ void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::end() { + m_spi->end(); +} +//------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } diff --git a/src/SpiDriver/SdSpiSoftDriver.h b/src/SpiDriver/SdSpiSoftDriver.h index a56e4eed..b49221ea 100644 --- a/src/SpiDriver/SdSpiSoftDriver.h +++ b/src/SpiDriver/SdSpiSoftDriver.h @@ -49,6 +49,8 @@ class SdSpiSoftDriver { } /** Deactivate SPI hardware. */ void deactivate() {} + /** deactivate SPI driver. */ + void end() {} /** Receive a byte. * * \return The byte. diff --git a/src/SpiDriver/SdSpiTeensy3.cpp b/src/SpiDriver/SdSpiTeensy3.cpp index 6ac830e7..d0303e3d 100644 --- a/src/SpiDriver/SdSpiTeensy3.cpp +++ b/src/SpiDriver/SdSpiTeensy3.cpp @@ -50,6 +50,10 @@ void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); } //------------------------------------------------------------------------------ +void SdSpiArduinoDriver::end() { + m_spi->end(); +} +//------------------------------------------------------------------------------ uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } diff --git a/src/common/ArduinoFiles.h b/src/common/ArduinoFiles.h index 82058022..748125de 100644 --- a/src/common/ArduinoFiles.h +++ b/src/common/ArduinoFiles.h @@ -24,7 +24,7 @@ */ #ifndef ArduinoFiles_h #define ArduinoFiles_h -#include "SdFatConfig.h" +#include "SysCall.h" //------------------------------------------------------------------------------ /** Arduino SD.h style flag for open for read. */ #ifndef FILE_READ @@ -91,9 +91,8 @@ class StreamFile : public stream_t, public BaseFile { * \return a pointer to replacement suggestion. */ #ifndef DOXYGEN_SHOULD_SKIP_THIS - const char* __attribute__((error("use getName(name, size)"))) name(); + char* __attribute__((error("use getName(name, size)"))) name(); #endif // DOXYGEN_SHOULD_SKIP_THIS - const char* name() const {return "use getName()";} /** Return the next available byte without consuming it. * * \return The byte if no error and not at eof else -1; diff --git a/src/common/DebugMacros.h b/src/common/DebugMacros.h index cf7cfc5f..7d0af924 100644 --- a/src/common/DebugMacros.h +++ b/src/common/DebugMacros.h @@ -24,7 +24,7 @@ */ #ifndef DebugMacros_h #define DebugMacros_h -#include "SdFatConfig.h" +#include "SysCall.h" // 0 - disable, 1 - fail, halt 2 - fail, halt, warn #define USE_DBG_MACROS 0 diff --git a/src/common/FmtNumber.cpp b/src/common/FmtNumber.cpp index da2bf32b..d9eb37e0 100644 --- a/src/common/FmtNumber.cpp +++ b/src/common/FmtNumber.cpp @@ -139,8 +139,7 @@ void divmod10(uint32_t in, uint32_t &div, uint32_t &mod) if (r > 9) mod = r - 10; else mod = r; } -// Hackers delight function is here: -// http://www.hackersdelight.org/hdcodetxt/divuc.c.txt +// See: https://github.com/hcs0/Hackers-Delight // Code below uses 8/10 = 0.1100 1100 1100 1100 1100 1100 1100 1100. // 15 ops including the multiply, or 17 elementary ops. unsigned divu10(unsigned n) { diff --git a/src/common/FsApiConstants.h b/src/common/FsApiConstants.h index 857bbb3b..3905e147 100644 --- a/src/common/FsApiConstants.h +++ b/src/common/FsApiConstants.h @@ -24,8 +24,7 @@ */ #ifndef FsApiConstants_h #define FsApiConstants_h -#include "SdFatConfig.h" - +#include "SysCall.h" #if USE_FCNTL_H #include /* values for GNU Arm Embedded Toolchain. diff --git a/src/common/BlockDevice.h b/src/common/FsBlockDevice.h similarity index 89% rename from src/common/BlockDevice.h rename to src/common/FsBlockDevice.h index f4f273b0..c0cabaff 100644 --- a/src/common/BlockDevice.h +++ b/src/common/FsBlockDevice.h @@ -22,12 +22,12 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#ifndef BlockDevice_h -#define BlockDevice_h +#ifndef FsBlockDevice_h +#define FsBlockDevice_h #include "SdCard/SdCard.h" #if HAS_SDIO_CLASS || USE_BLOCK_DEVICE_INTERFACE -typedef BlockDeviceInterface BlockDevice; +typedef FsBlockDeviceInterface FsBlockDevice; #else -typedef SdCard BlockDevice; +typedef SdCard FsBlockDevice; #endif -#endif // BlockDevice_h +#endif // FsBlockDevice_h diff --git a/src/common/BlockDeviceInterface.h b/src/common/FsBlockDeviceInterface.h similarity index 88% rename from src/common/BlockDeviceInterface.h rename to src/common/FsBlockDeviceInterface.h index 1d85cdd6..ecd99121 100644 --- a/src/common/BlockDeviceInterface.h +++ b/src/common/FsBlockDeviceInterface.h @@ -24,22 +24,24 @@ */ /** * \file - * \brief BlockDeviceInterface include file. + * \brief FsBlockDeviceInterface include file. */ -#ifndef BlockDeviceInterface_h -#define BlockDeviceInterface_h +#ifndef FsBlockDeviceInterface_h +#define FsBlockDeviceInterface_h #include #include -#include "SdFatConfig.h" /** - * \class BlockDeviceInterface - * \brief BlockDeviceInterface class. + * \class FsBlockDeviceInterface + * \brief FsBlockDeviceInterface class. */ -class BlockDeviceInterface { +class FsBlockDeviceInterface { public: - virtual ~BlockDeviceInterface() {} + virtual ~FsBlockDeviceInterface() {} + + /** end use of device */ + virtual void end() {} /** - * Check for BlockDevice busy. + * Check for FsBlockDevice busy. * * \return true if busy else false. */ @@ -90,4 +92,4 @@ class BlockDeviceInterface { */ virtual bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns) = 0; }; -#endif // BlockDeviceInterface_h +#endif // FsBlockDeviceInterface_h diff --git a/src/common/FsCache.h b/src/common/FsCache.h index 1d42008c..f5d8ae80 100644 --- a/src/common/FsCache.h +++ b/src/common/FsCache.h @@ -29,7 +29,7 @@ * \brief Common cache code for exFAT and FAT. */ #include "SysCall.h" -#include "BlockDevice.h" +#include "FsBlockDevice.h" /** * \class FsCache * \brief Sector cache. @@ -127,7 +127,7 @@ class FsCache { /** Initialize the cache. * \param[in] blockDev Block device for this cache. */ - void init(BlockDevice* blockDev) { + void init(FsBlockDevice* blockDev) { m_blockDev = blockDev; invalidate(); } @@ -153,6 +153,12 @@ class FsCache { bool isDirty() { return m_status & CACHE_STATUS_DIRTY; } + /** Prepare cache to access sector. + * \param[in] sector Sector to read. + * \param[in] option mode for cached sector. + * \return Address of cached sector. + */ + uint8_t* prepare(uint32_t sector, uint8_t option); /** \return Logical sector number for cached sector. */ uint32_t sector() { return m_sector; @@ -163,12 +169,6 @@ class FsCache { void setMirrorOffset(uint32_t offset) { m_mirrorOffset = offset; } - /** Prepare cache to access sector. - * \param[in] sector Sector to read. - * \param[in] option mode for cached sector. - * \return Address of cached sector. - */ - uint8_t* prepare(uint32_t sector, uint8_t option); /** Write current sector if dirty. * \return true for success or false for failure. */ @@ -176,7 +176,7 @@ class FsCache { private: uint8_t m_status; - BlockDevice* m_blockDev; + FsBlockDevice* m_blockDev; uint32_t m_mirrorOffset; uint32_t m_sector; uint8_t m_buffer[512]; diff --git a/src/common/FsName.h b/src/common/FsName.h index 6e7a0a53..d7cc425c 100644 --- a/src/common/FsName.h +++ b/src/common/FsName.h @@ -24,7 +24,7 @@ */ #ifndef FsName_h #define FsName_h -#include "SdFatConfig.h" +#include "SysCall.h" #include /** * \file diff --git a/src/common/PrintBasic.cpp b/src/common/PrintBasic.cpp new file mode 100644 index 00000000..c0c6d581 --- /dev/null +++ b/src/common/PrintBasic.cpp @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2011-2020 Bill Greiman + * This file is part of the SdFat library for SD memory cards. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining 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. + */ +#include "PrintBasic.h" +#if ENABLE_ARDUINO_FEATURES == 0 +#include + +size_t PrintBasic::print(long n, uint8_t base) { + if (n < 0 && base == 10) { + return print('-') + printNum(-n, base); + } + return printNum(n, base); +} +size_t PrintBasic::printNum(unsigned long n, uint8_t base) { + const uint8_t DIM = 8*sizeof(long); + char buf[DIM]; + char *str = &buf[DIM]; + + if (base < 2) return 0; + + do { + char c = n%base; + n /= base; + *--str = c + (c < 10 ? '0' : 'A' - 10); + } while (n); + return write(str, &buf[DIM] - str); +} + +size_t PrintBasic::printDouble(double n, uint8_t prec) { + // Max printable 32-bit floating point number. AVR uses 32-bit double. + const double maxfp = static_cast(0XFFFFFF00UL); + size_t rtn = 0; + + if (isnan(n)) { + return write("NaN"); + } + if (n < 0) { + n = -n; + rtn += print('-'); + } + if (isinf(n)) { + return rtn + write("Inf"); + } + if (n > maxfp) { + return rtn + write("Ovf"); + } + + double round = 0.5; + for (uint8_t i = 0; i < prec; ++i) { + round *= 0.1; + } + + n += round; + + uint32_t whole = (uint32_t)n; + rtn += print(whole); + + if (prec) { + rtn += print('.'); + double fraction = n - static_cast(whole); + for (uint8_t i = 0; i < prec; i++) { + fraction *= 10.0; + uint8_t digit = fraction; + rtn += print(digit); + fraction -= digit; + } + } + return rtn; +} +#endif // ENABLE_ARDUINO_FEATURES == 0 diff --git a/src/common/PrintBasic.h b/src/common/PrintBasic.h new file mode 100644 index 00000000..f1743715 --- /dev/null +++ b/src/common/PrintBasic.h @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2011-2020 Bill Greiman + * This file is part of the SdFat library for SD memory cards. + * + * MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining 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 PrintBasic_h +#define PrintBasic_h +/** + * \file + * \brief Stream/Print like replacement for non-Arduino systems. + */ +#include +#include +#include +#include "../SdFatConfig.h" + +#ifndef F +#if defined(__AVR__) +#include +class __FlashStringHelper; +#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) +#else // defined(__AVR__) +#define F(str) (str) +#endif // defined(__AVR__) +#endif // F + +#ifdef BIN +#undef BIN +#endif // BIN +#define BIN 2 +#define OCT 8 +#define DEC 10 +#define HEX 16 + +class PrintBasic { + public: + PrintBasic() : m_error(0) {} + + void clearWriteError() { + setWriteError(0); + } + int getWriteError() { + return m_error; + } + size_t print(char c) { + return write(c); + } + size_t print(const char* str) { + return write(str); + } + size_t print(const __FlashStringHelper *str) { +#ifdef __AVR__ + PGM_P p = reinterpret_cast(str); + size_t n = 0; + for (uint8_t c; (c = pgm_read_byte(p + n)) && write(c); n++) {} + return n; +#else // __AVR__ + return print(reinterpret_cast(str)); +#endif // __AVR__ + } + size_t println(const __FlashStringHelper *str) { +#ifdef __AVR__ + return print(str) + println(); +#else // __AVR__ + return println(reinterpret_cast(str)); +#endif // __AVR__ + } + size_t print(double n, uint8_t prec = 2) { + return printDouble(n, prec); + } + size_t print(signed char n, uint8_t base = 10) { + return print((long)n, base); + } + size_t print(unsigned char n, uint8_t base = 10) { + return print((unsigned long)n, base); + } + size_t print(int n, uint8_t base = 10) { + return print((long)n, base); + } + size_t print(unsigned int n, uint8_t base = 10) { + return print((unsigned long)n, base); + } + size_t print(long n, uint8_t base = 10); + size_t print(unsigned long n, uint8_t base = 10) { + return printNum(n, base); + } + size_t println() { + return write("\r\n"); + } + size_t println(char c) { + return write(c) + println(); + } + size_t println(const char* str) { + return print(str) + println(); + } + size_t println(double n, uint8_t prec = 2) { + return print(n, prec) + println(); + } + size_t println(signed char n, uint8_t base = 10) { + return print(n, base) + println(); + } + size_t println(unsigned char n, uint8_t base = 10) { + return print(n, base) + println(); + } + size_t println(int n, uint8_t base = 10) { + return print(n, base) + println(); + } + size_t println(unsigned int n, uint8_t base = 10) { + return print(n, base) + println(); + } + size_t println(long n, uint8_t base = 10) { + return print(n, base) + println(); + } + size_t println(unsigned long n, uint8_t base = 10) { + return print(n, base) + println(); + } + size_t write(const char *str) { + return write(str, strlen(str)); + } + virtual size_t write(uint8_t b) = 0; + + virtual size_t write(const uint8_t* buffer, size_t size) { + size_t i; + for (i = 0; i < size; i++) { + if (!write(buffer[i])) break; + } + return i; + } + size_t write(const char *buffer, size_t size) { + return write((const uint8_t*)buffer, size); + } + + protected: + void setWriteError(int err = 1) { + m_error = err; + } + + private: + size_t printDouble(double n, uint8_t prec); + size_t printNum(unsigned long n, uint8_t base); + int m_error; +}; +//------------------------------------------------------------------------------ +class StreamBasic : public PrintBasic { + public: + virtual int available() = 0; + virtual int peek() = 0; + virtual int read() = 0; +}; +#endif // PrintBasic_h diff --git a/src/common/SysCall.h b/src/common/SysCall.h index 67c1f4dd..c7be07e1 100644 --- a/src/common/SysCall.h +++ b/src/common/SysCall.h @@ -30,30 +30,13 @@ #define SysCall_h #include #include -#include "SdFatConfig.h" +#include "../SdFatConfig.h" #if __cplusplus < 201103 #warning nullptr defined /** Define nullptr if not C++11 */ #define nullptr NULL #endif // __cplusplus < 201103 //------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -/** - * \class SysCall - * \brief SysCall - Class to wrap system calls. - */ -class SysCall { - public: - /** Halt execution of this thread. */ - static void halt() { - while (1) { - yield(); - } - } - /** Yield to other threads. */ - static void yield(); -}; #if ENABLE_ARDUINO_FEATURES #if defined(ARDUINO) /** Use Arduino Print. */ @@ -69,28 +52,11 @@ typedef Stream stream_t; #define F(str) (str) #endif // F //------------------------------------------------------------------------------ -#if defined(PLATFORM_ID) // Only defined if a Particle device -inline void SysCall::yield() { - // Recommended to only call Particle.process() if system threading is disabled - if (system_thread_get_state(NULL) == spark::feature::DISABLED) { - Particle.process(); - } -} -#elif defined(ARDUINO) -inline void SysCall::yield() { - // Use the external Arduino yield() function. - ::yield(); -} -#else // defined(PLATFORM_ID) -inline void SysCall::yield() {} -#endif // defined(PLATFORM_ID) -//------------------------------------------------------------------------------ #else // ENABLE_ARDUINO_FEATURES #include "PrintBasic.h" /** If not Arduino */ typedef PrintBasic print_t; /** If not Arduino */ typedef PrintBasic stream_t; -inline void SysCall::yield() {} #endif // ENABLE_ARDUINO_FEATURES #endif // SysCall_h diff --git a/src/iostream/ArduinoStream.h b/src/iostream/ArduinoStream.h index 803cca76..1fbce34e 100644 --- a/src/iostream/ArduinoStream.h +++ b/src/iostream/ArduinoStream.h @@ -28,7 +28,6 @@ * \file * \brief ArduinoInStream and ArduinoOutStream classes */ -#include "SdFatConfig.h" #include "bufstream.h" //============================================================================== /** @@ -54,7 +53,7 @@ class ArduinoInStream : public ibufstream { uint32_t t; m_line[0] = '\0'; while (!m_hw->available()) { - SysCall::yield(); + yield(); } while (1) { @@ -111,7 +110,7 @@ class ArduinoOutStream : public ostream { * * \param[in] pr Print object for this ArduinoOutStream. */ - explicit ArduinoOutStream(Print& pr) : m_pr(&pr) {} + explicit ArduinoOutStream(print_t& pr) : m_pr(&pr) {} protected: /// @cond SHOW_PROTECTED @@ -146,6 +145,6 @@ class ArduinoOutStream : public ostream { /// @endcond private: ArduinoOutStream() {} - Print* m_pr; + print_t* m_pr; }; #endif // ArduinoStream_h diff --git a/src/iostream/StdioStream.h b/src/iostream/StdioStream.h index cc4f1074..76998d7f 100644 --- a/src/iostream/StdioStream.h +++ b/src/iostream/StdioStream.h @@ -440,7 +440,7 @@ class StdioStream : private StreamBaseFile { return n > 0 ? n : 0; } //---------------------------------------------------------------------------- - /** Print a number. + /** Print a number. * * \param[in] val the number to be printed. * diff --git a/src/iostream/ios.h b/src/iostream/ios.h index a9db117e..cb22a582 100644 --- a/src/iostream/ios.h +++ b/src/iostream/ios.h @@ -33,7 +33,7 @@ /** For internal use in c++ streams */ typedef fspos_t pos_t; //============================================================================== -#if SDFAT_FILE_TYPE == 1 +#if SDFAT_FILE_TYPE == 1 || defined(DOXYGEN) /** Set File type for iostreams. */ typedef FatFile StreamBaseFile; #elif SDFAT_FILE_TYPE == 2