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