From 1535ac2b0332c22da26ca876fd2a04641dffadb4 Mon Sep 17 00:00:00 2001 From: Bill Greiman Date: Sat, 5 Dec 2020 05:53:23 -0800 Subject: [PATCH] Timestamp fix, edit src for cplint errors Add time st --- examples/AvrAdcLogger/AvrAdcLogger.ino | 44 +- .../BackwardCompatibility.ino | 8 +- examples/ExFatFormatter/ExFatFormatter.ino | 22 +- examples/ExFatLogger/ExFatLogger.ino | 44 +- examples/OpenNext/OpenNext.ino | 10 +- examples/QuickStart/QuickStart.ino | 18 +- examples/ReadCsvFile/ReadCsvFile.ino | 30 +- .../RtcTimestampTest/RtcTimestampTest.ino | 120 ++++- examples/STM32Test/STM32Test.ino | 12 +- examples/SdFormatter/SdFormatter.ino | 18 +- examples/SdInfo/SdInfo.ino | 13 +- examples/SoftwareSpi/SoftwareSpi.ino | 4 +- .../TeensyRtcTimestamp/TeensyRtcTimestamp.ino | 18 +- examples/TeensySdioDemo/TeensySdioDemo.ino | 31 +- .../UserChipSelectFunction.ino | 6 +- examples/UserSPIDriver/UserSPIDriver.ino | 4 +- examples/bench/bench.ino | 14 +- .../#attic/AnalogLogger/AnalogLogger.ino | 2 +- .../BaseExtCaseTest/BaseExtCaseTest.ino | 4 +- .../#attic/HelloWorld/HelloWorld.ino | 2 +- .../PrintBenchmarkSD/PrintBenchmarkSD.ino | 6 +- .../examplesV1/#attic/SD_Size/SD_Size.ino | 4 +- .../examplesV1/#attic/SdFatSize/SdFatSize.ino | 6 +- .../#attic/StreamParseInt/StreamParseInt.ino | 2 +- examples/examplesV1/#attic/append/append.ino | 4 +- .../examplesV1/#attic/average/average.ino | 4 +- .../examplesV1/#attic/benchSD/benchSD.ino | 6 +- .../examplesV1/#attic/bufstream/bufstream.ino | 4 +- .../examplesV1/#attic/cin_cout/cin_cout.ino | 2 +- .../examplesV1/#attic/eventlog/eventlog.ino | 2 +- .../#attic/fgetsRewrite/fgetsRewrite.ino | 4 +- .../examplesV1/#attic/readlog/readlog.ino | 4 +- .../LowLatencyLoggerADXL345/UserFunctions.cpp | 8 +- .../LowLatencyLoggerMPU6050/UserFunctions.cpp | 4 +- examples/examplesV1/OpenNext/OpenNext.ino | 6 +- .../PrintBenchmark/PrintBenchmark.ino | 2 +- examples/examplesV1/RawWrite/RawWrite.ino | 8 +- examples/examplesV1/ReadCsv/ReadCsv.ino | 14 +- .../examplesV1/ReadCsvArray/ReadCsvArray.ino | 10 +- .../ReadCsvStream/ReadCsvStream.ino | 6 +- examples/examplesV1/STM32Test/STM32Test.ino | 4 +- .../examplesV1/SdFormatter/SdFormatter.ino | 14 +- examples/examplesV1/SdInfo/SdInfo.ino | 12 +- .../examplesV1/SoftwareSpi/SoftwareSpi.ino | 4 +- examples/examplesV1/StdioBench/StdioBench.ino | 6 +- .../TeensySdioDemo/TeensySdioDemo.ino | 24 +- examples/examplesV1/Timestamp/Timestamp.ino | 4 +- examples/examplesV1/TwoCards/TwoCards.ino | 4 +- examples/examplesV1/dataLogger/dataLogger.ino | 6 +- examples/examplesV1/fgets/fgets.ino | 4 +- examples/examplesV1/formatting/formatting.ino | 2 +- examples/examplesV1/getline/getline.ino | 4 +- examples/examplesV1/wipe/wipe.ino | 6 +- extras/cpplint.py | 185 +++++-- extras/cpplint.txt | 7 - library.properties | 2 +- src/DigitalIO/SoftSPI.h | 2 +- src/ExFatLib/ExFatDbg.cpp | 480 +++++++++--------- src/ExFatLib/ExFatFile.cpp | 144 ++++-- src/ExFatLib/ExFatFile.h | 63 ++- src/ExFatLib/ExFatFilePrint.cpp | 135 +++-- src/ExFatLib/ExFatFileWrite.cpp | 38 +- src/ExFatLib/ExFatFormatter.cpp | 14 +- src/ExFatLib/ExFatPartition.cpp | 152 +++--- src/ExFatLib/ExFatPartition.h | 24 +- src/ExFatLib/ExFatVolume.cpp | 4 +- src/ExFatLib/ExFatVolume.h | 2 +- src/ExFatLib/upcase.cpp | 97 ++-- src/FatLib/FatDbg.cpp | 1 - src/FatLib/FatFile.cpp | 154 ++++-- src/FatLib/FatFile.h | 63 ++- src/FatLib/FatFileLFN.cpp | 43 +- src/FatLib/FatFilePrint.cpp | 32 +- src/FatLib/FatFileSFN.cpp | 29 +- src/FatLib/FatFormatter.cpp | 12 +- src/FatLib/FatPartition.cpp | 20 +- src/FatLib/FatPartition.h | 2 +- src/FatLib/FatVolume.cpp | 4 +- src/FsLib/FsFile.h | 65 ++- src/FsLib/FsVolume.h | 2 +- src/SdCard/SdSpiCard.cpp | 221 ++++---- src/SdCard/SdSpiCard.h | 2 +- src/SdCard/SdioCard.h | 2 +- src/SdCard/SdioTeensy.cpp | 6 +- src/SdCard/SdioTeensy.h | 2 +- src/SdFat.h | 16 +- src/SdFatConfig.h | 23 +- src/SpiDriver/SdSpiArtemis.cpp | 4 +- src/SpiDriver/SdSpiBaseClass.h | 2 +- src/common/BlockDeviceInterface.h | 8 +- src/common/CompileDateTime.h | 74 +++ src/common/FmtNumber.cpp | 2 +- src/common/FsDateTime.cpp | 2 +- src/common/FsDateTime.h | 46 +- src/common/PrintBasic.h | 4 +- src/common/SysCall.h | 5 +- src/iostream/StdioStream.cpp | 4 +- src/iostream/StreamBaseClass.cpp | 2 +- src/iostream/bufstream.h | 4 +- src/iostream/fstream.h | 4 +- src/iostream/istream.cpp | 2 +- src/iostream/ostream.cpp | 53 +- src/iostream/ostream.h | 70 ++- 103 files changed, 1810 insertions(+), 1148 deletions(-) delete mode 100644 extras/cpplint.txt create mode 100644 src/common/CompileDateTime.h diff --git a/examples/AvrAdcLogger/AvrAdcLogger.ino b/examples/AvrAdcLogger/AvrAdcLogger.ino index 558439c3..8eedaec7 100644 --- a/examples/AvrAdcLogger/AvrAdcLogger.ino +++ b/examples/AvrAdcLogger/AvrAdcLogger.ino @@ -44,10 +44,16 @@ MinimumSerial MinSerial; //------------------------------------------------------------------------------ // Set USE_RTC nonzero for file timestamps. // RAM use will be marginal on Uno with RTClib. +// Set USE_RTC nonzero for file timestamps. +// RAM use will be marginal on Uno with RTClib. +// 0 - RTC not used +// 1 - DS1307 +// 2 - DS3231 +// 3 - PCF8523 #define USE_RTC 0 #if USE_RTC #include "RTClib.h" -#endif +#endif // USE_RTC //------------------------------------------------------------------------------ // Pin definitions. // @@ -141,7 +147,7 @@ const uint16_t MIN_ADC_CYCLES = 15; // Extra cpu cycles to setup ADC with more than one pin per sample. const uint16_t ISR_SETUP_ADC = PIN_COUNT > 1 ? 100 : 0; -// Maximum cycles for timer0 system interrupt, millis, micros. +// Maximum cycles for timer0 system interrupt. const uint16_t ISR_TIMER0 = 160; //============================================================================== const uint32_t MAX_FILE_SIZE = MAX_FILE_SIZE_MiB << 20; @@ -303,8 +309,15 @@ void printUnusedStack() { } //------------------------------------------------------------------------------ #if USE_RTC +#if USE_RTC == 1 RTC_DS1307 rtc; - +#elif USE_RTC == 2 +RTC_DS3231 rtc; +#elif USE_RTC == 3 +RTC_PCF8523 rtc; +#else // USE_RTC == type +#error USE_RTC type not implemented. +#endif // USE_RTC == type // Call back for file timestamps. Only called for file create and sync(). void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) { DateTime now = rtc.now(); @@ -553,6 +566,15 @@ void binaryToCsv() { Serial.println(F(" Seconds")); } //------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} +//------------------------------------------------------------------------------ void createBinFile() { binFile.close(); while (sd.exists(binName)) { @@ -719,7 +741,7 @@ void logData() { //------------------------------------------------------------------------------ void openBinFile() { char name[NAME_DIM]; - serialClearInput(); + clearSerialInput(); Serial.println(F("Enter file name")); if (!serialReadLine(name, sizeof(name))) { return; @@ -772,12 +794,6 @@ void printData() { Serial.println(F("Done")); } //------------------------------------------------------------------------------ -void serialClearInput() { - do { - delay(10); - } while (Serial.read() >= 0); -} -//------------------------------------------------------------------------------ bool serialReadLine(char* str, size_t size) { size_t n = 0; while(!Serial.available()) { @@ -840,9 +856,7 @@ void setup(void) { void loop(void) { printUnusedStack(); // Read any Serial data. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); Serial.println(); Serial.println(F("type:")); Serial.println(F("b - open existing bin file")); @@ -860,9 +874,7 @@ void loop(void) { digitalWrite(ERROR_LED_PIN, LOW); } // Read any Serial data. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); if (c == 'b') { openBinFile(); diff --git a/examples/BackwardCompatibility/BackwardCompatibility.ino b/examples/BackwardCompatibility/BackwardCompatibility.ino index db109930..1ca69ce4 100644 --- a/examples/BackwardCompatibility/BackwardCompatibility.ino +++ b/examples/BackwardCompatibility/BackwardCompatibility.ino @@ -1,6 +1,6 @@ // A simple read/write example for SD.h. // Mostly from the SD.h ReadWrite example. -// +// // Your SD must be formatted FAT16/FAT32. // // Set USE_SD_H nonzero to use SD.h. @@ -28,14 +28,14 @@ void setup() { #if USE_SD_H Serial.println(F("Using SD.h. Set USE_SD_H zero to use SdFat.h.")); #else // USE_SD_H - Serial.println(F("Using SdFat.h. Set USE_SD_H nonzero to use SD.h.")); -#endif // USE_SD_H + Serial.println(F("Using SdFat.h. Set USE_SD_H nonzero to use SD.h.")); +#endif // USE_SD_H Serial.println(F("\nType any character to begin.")); while (!Serial.available()) { yield(); } Serial.print("Initializing SD card..."); - + if (!SD.begin(SD_CS_PIN)) { Serial.println("initialization failed!"); return; diff --git a/examples/ExFatFormatter/ExFatFormatter.ino b/examples/ExFatFormatter/ExFatFormatter.ino index 79606788..b496f5ff 100644 --- a/examples/ExFatFormatter/ExFatFormatter.ino +++ b/examples/ExFatFormatter/ExFatFormatter.ino @@ -3,7 +3,7 @@ /* Change the value of SD_CS_PIN if you are using SPI and - your hardware does not use the default value, SS. + your hardware does not use the default value, SS. Common values are: Arduino Ethernet shield: pin 4 Sparkfun SD shield: pin 8 @@ -31,6 +31,15 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN; SdExFat sd; //------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} +//------------------------------------------------------------------------------ void errorHalt() { sd.printSdError(&Serial); SysCall::halt(); @@ -41,20 +50,17 @@ void setup() { Serial.begin(9600); while (!Serial) {} Serial.println(F("Type any character to begin")); - + while (!Serial.available()) { yield(); } - do { - delay(10); - } while(Serial.read() >= 0); - + clearSerialInput(); Serial.println(); Serial.println(F( "Your SD will be formated exFAT.\r\n" "All data on the SD will be lost.\r\n" "Type 'Y' to continue.\r\n")); - + while (!Serial.available()) { yield(); } @@ -64,7 +70,7 @@ void setup() { } if (!sd.cardBegin(SD_CONFIG)) { error("cardBegin failed"); - } + } if(!sd.format(&Serial)) { error("format failed"); } diff --git a/examples/ExFatLogger/ExFatLogger.ino b/examples/ExFatLogger/ExFatLogger.ino index 48750050..d9158213 100644 --- a/examples/ExFatLogger/ExFatLogger.ino +++ b/examples/ExFatLogger/ExFatLogger.ino @@ -24,6 +24,10 @@ const uint32_t LOG_INTERVAL_USEC = 2000; // Set USE_RTC nonzero for file timestamps. // RAM use will be marginal on Uno with RTClib. +// 0 - RTC not used +// 1 - DS1307 +// 2 - DS3231 +// 3 - PCF8523 #define USE_RTC 0 #if USE_RTC #include "RTClib.h" @@ -151,8 +155,15 @@ file_t csvFile; char binName[] = "ExFatLogger00.bin"; //------------------------------------------------------------------------------ #if USE_RTC +#if USE_RTC == 1 RTC_DS1307 rtc; - +#elif USE_RTC == 2 +RTC_DS3231 rtc; +#elif USE_RTC == 3 +RTC_PCF8523 rtc; +#else // USE_RTC == type +#error USE_RTC type not implemented. +#endif // USE_RTC == type // Call back for file timestamps. Only called for file create and sync(). void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) { DateTime now = rtc.now(); @@ -211,6 +222,15 @@ void binaryToCsv() { Serial.print(0.001*(millis() - t0)); Serial.println(F(" Seconds")); } +//------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} //------------------------------------------------------------------------------- void createBinFile() { binFile.close(); @@ -261,7 +281,7 @@ bool createCsvFile() { if (!csvFile.open(csvName, O_WRONLY | O_CREAT | O_TRUNC)) { error("open csvFile failed"); } - serialClearInput(); + clearSerialInput(); Serial.print(F("Writing: ")); Serial.print(csvName); Serial.println(F(" - type any character to stop")); @@ -289,7 +309,7 @@ void logData() { if (binFile.write(fifoBuf, 512) != 512) { error("write first sector failed"); } - serialClearInput(); + clearSerialInput(); Serial.println(F("Type any character to stop")); // Wait until SD is not busy. @@ -397,7 +417,7 @@ void logData() { //------------------------------------------------------------------------------ void openBinFile() { char name[FILE_NAME_DIM]; - serialClearInput(); + clearSerialInput(); Serial.println(F("Enter file name")); if (!serialReadLine(name, sizeof(name))) { return; @@ -425,7 +445,7 @@ void printData() { if (!binFile.seekSet(512)) { error("seek failed"); } - serialClearInput(); + clearSerialInput(); Serial.println(F("type any character to stop\n")); delay(1000); printRecord(&Serial, nullptr); @@ -439,16 +459,10 @@ void printData() { } //------------------------------------------------------------------------------ void printUnusedStack() { -#if HAS_UNUSED_STACK +#if HAS_UNUSED_STACK Serial.print(F("\nUnused stack: ")); Serial.println(UnusedStack()); -#endif // HAS_UNUSED_STACK -} -//------------------------------------------------------------------------------ -void serialClearInput() { - do { - delay(10); - } while (Serial.read() >= 0); +#endif // HAS_UNUSED_STACK } //------------------------------------------------------------------------------ bool serialReadLine(char* str, size_t size) { @@ -476,7 +490,7 @@ void testSensor() { const uint32_t interval = 200000; int32_t diff; data_t data; - serialClearInput(); + clearSerialInput(); Serial.println(F("\nTesting - type any character to stop\n")); delay(1000); printRecord(&Serial, nullptr); @@ -538,7 +552,7 @@ void setup() { void loop() { printUnusedStack(); // Read any Serial data. - serialClearInput(); + clearSerialInput(); if (ERROR_LED_PIN >= 0) { digitalWrite(ERROR_LED_PIN, LOW); diff --git a/examples/OpenNext/OpenNext.ino b/examples/OpenNext/OpenNext.ino index a00dcdba..b5a8ace0 100644 --- a/examples/OpenNext/OpenNext.ino +++ b/examples/OpenNext/OpenNext.ino @@ -8,7 +8,7 @@ #define SD_FAT_TYPE 0 /* Change the value of SD_CS_PIN if you are using SPI and - your hardware does not use the default value, SS. + your hardware does not use the default value, SS. Common values are: Arduino Ethernet shield: pin 4 Sparkfun SD shield: pin 8 @@ -57,12 +57,12 @@ FsFile file; //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } - + Serial.println("Type any character to start"); while (!Serial.available()) { SysCall::yield(); @@ -72,7 +72,7 @@ void setup() { if (!sd.begin(SD_CONFIG)) { sd.initErrorHalt(&Serial); } - // Open root directory + // Open root directory if (!dir.open("/")){ error("dir.open failed"); } diff --git a/examples/QuickStart/QuickStart.ino b/examples/QuickStart/QuickStart.ino index d4fe793b..ec1955e9 100644 --- a/examples/QuickStart/QuickStart.ino +++ b/examples/QuickStart/QuickStart.ino @@ -48,6 +48,15 @@ void cardOrSpeed() { cout << F("Edit SPI_SPEED in this program to change it.\n"); } +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} + void reformatMsg() { cout << F("Try reformatting the card. For best results use\n"); cout << F("the SdFormatter program in SdFat/examples or download\n"); @@ -88,9 +97,7 @@ void setup() { bool firstTry = true; void loop() { // Read any existing Serial data. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); if (!firstTry) { cout << F("\nRestarting\n"); @@ -171,9 +178,8 @@ void loop() { return; } // Read any extra Serial data. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); + cout << F("\nSuccess! Type any character to restart.\n"); while (!Serial.available()) { SysCall::yield(); diff --git a/examples/ReadCsvFile/ReadCsvFile.ino b/examples/ReadCsvFile/ReadCsvFile.ino index c9598c31..a63dd847 100644 --- a/examples/ReadCsvFile/ReadCsvFile.ino +++ b/examples/ReadCsvFile/ReadCsvFile.ino @@ -5,7 +5,7 @@ #define SD_FAT_TYPE 0 /* Change the value of SD_CS_PIN if you are using SPI and - your hardware does not use the default value, SS. + your hardware does not use the default value, SS. Common values are: Arduino Ethernet shield: pin 4 Sparkfun SD shield: pin 8 @@ -63,25 +63,25 @@ bool parseLine(char* str) { // Set strtok start of line. str = strtok(str, ","); if (!str) return false; - + // Print text field. Serial.println(str); - + // Subsequent calls to strtok expects a null pointer. str = strtok(nullptr, ","); if (!str) return false; - + // Convert string to long integer. int32_t i32 = strtol(str, &ptr, 0); if (str == ptr || *skipSpace(ptr)) return false; Serial.println(i32); - + str = strtok(nullptr, ","); if (!str) return false; - + // strtoul accepts a leading minus with unexpected results. if (*skipSpace(str) == '-') return false; - + // Convert string to unsigned long integer. uint32_t u32 = strtoul(str, &ptr, 0); if (str == ptr || *skipSpace(ptr)) return false; @@ -89,20 +89,20 @@ bool parseLine(char* str) { str = strtok(nullptr, ","); if (!str) return false; - + // Convert string to double. double d = strtod(str, &ptr); if (str == ptr || *skipSpace(ptr)) return false; Serial.println(d); - + // Check for extra fields. return strtok(nullptr, ",") == nullptr; } //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { yield(); } @@ -117,7 +117,7 @@ void setup() { } // Remove any existing file. if (sd.exists("ReadCsvDemo.csv")) { - sd.remove("ReadCsvDemo.csv"); + sd.remove("ReadCsvDemo.csv"); } // Create the file. if (!file.open("ReadCsvDemo.csv", FILE_WRITE)) { @@ -128,14 +128,14 @@ void setup() { "abc,123,456,7.89\r\n" "def,-321,654,-9.87\r\n" "ghi,333,0xff,5.55")); - + // Rewind file for read. file.rewind(); - + while (file.available()) { int n = file.fgets(line, sizeof(line)); if (n <= 0) { - error("fgets failed"); + error("fgets failed"); } if (line[n-1] != '\n' && n == (sizeof(line) - 1)) { error("line too long"); diff --git a/examples/RtcTimestampTest/RtcTimestampTest.ino b/examples/RtcTimestampTest/RtcTimestampTest.ino index 24ab50af..912a787c 100644 --- a/examples/RtcTimestampTest/RtcTimestampTest.ino +++ b/examples/RtcTimestampTest/RtcTimestampTest.ino @@ -4,13 +4,19 @@ #include "SdFat.h" // https://github.com/adafruit/RTClib #include "RTClib.h" +// Set RTC_TYPE for file timestamps. +// 0 - millis() +// 1 - DS1307 +// 2 - DS3231 +// 3 - PCF8523 +#define RTC_TYPE 3 // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. #define SD_FAT_TYPE 0 /* Change the value of SD_CS_PIN if you are using SPI and - your hardware does not use the default value, SS. + your hardware does not use the default value, SS. Common values are: Arduino Ethernet shield: pin 4 Sparkfun SD shield: pin 8 @@ -50,7 +56,19 @@ FsFile file; #error Invalid SD_FAT_TYPE #endif // SD_FAT_TYPE + +#if RTC_TYPE == 0 +RTC_Millis rtc; +#elif RTC_TYPE == 1 RTC_DS1307 rtc; +#elif RTC_TYPE == 2 +RTC_DS3231 rtc; +#elif RTC_TYPE == 3 +RTC_PCF8523 rtc; +#else // RTC_TYPE == type +#error RTC_TYPE type not implemented. +#endif // RTC_TYPE == type + //------------------------------------------------------------------------------ // Call back for file timestamps. Only called for file create and sync(). void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) { @@ -61,46 +79,111 @@ void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) { // Return time using FS_TIME macro to format fields. *time = FS_TIME(now.hour(), now.minute(), now.second()); - + // Return low time bits in units of 10 ms, 0 <= ms10 <= 199. *ms10 = now.second() & 1 ? 100 : 0; } //------------------------------------------------------------------------------ +#define error(msg) (Serial.println(F("error " msg)), false) +//------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} +//------------------------------------------------------------------------------ +void getLine(char* line, size_t size) { + size_t i = 0; + uint32_t t; + line[0] = '\0'; + while (!Serial.available()) { + yield(); + } + while (true) { + t = millis() + 10; + while (!Serial.available()) { + if (millis() > t){ + return; + } + } + int c = Serial.read(); + if (i >= (size - 1) || c == '\r' || c == '\n' ) { + return; + } + line[i++] = c; + line[i] = '\0'; + } +} +//------------------------------------------------------------------------------ void printField(Print* pr, char sep, uint8_t v) { if (sep) { pr->write(sep); - } + } if (v < 10) { pr->write('0'); } pr->print(v); } -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ void printNow(Print* pr) { DateTime now = rtc.now(); pr->print(now.year()); printField(pr, '-',now.month()); - printField(pr, '-',now.day()); + printField(pr, '-',now.day()); printField(pr, ' ',now.hour()); printField(pr, ':',now.minute()); printField(pr, ':',now.second()); } //------------------------------------------------------------------------------ +bool setRtc() { + uint16_t y; + uint8_t m, d, hh, mm, ss; + char line[30]; + char* ptr; + + clearSerialInput(); + Serial.println(F("Enter: YYYY-MM-DD hh:mm:ss")); + getLine(line, sizeof(line)); + Serial.print(F("Input: ")); + Serial.println(line); + + y = strtol(line, &ptr, 0); + if (*ptr++ != '-' || y < 2000 || y > 2099) return error("year"); + m = strtol(ptr, &ptr, 0); + if (*ptr++ != '-' || m < 1 || m > 12) return error("month"); + d = strtol(ptr, &ptr, 0); + if (d < 1 || d > 31) return error("day"); + hh = strtol(ptr, &ptr, 0); + if (*ptr++ != ':' || hh > 23) return error("hour"); + mm = strtol(ptr, &ptr, 0); + if (*ptr++ != ':' || mm > 59) return error("minute"); + ss = strtol(ptr, &ptr, 0); + if (ss > 59) return error("second"); + + rtc.adjust(DateTime(y, m, d, hh, mm, ss)); + Serial.print(F("RTC set to ")); + printNow(&Serial); + Serial.println(); + return true; +} +//------------------------------------------------------------------------------ void setup() { Serial.begin(9600); while (!Serial) { yield(); } - Serial.println(F("Type any character to begin")); - while (!Serial.available()) { - yield(); - } +#if RTC_TYPE == 0 + rtc.begin(DateTime(F(__DATE__), F(__TIME__))); +#else // RTC_TYPE if (!rtc.begin()) { Serial.println(F("rtc.begin failed")); return; } if (!rtc.isrunning()) { - Serial.println("RTC is NOT running!"); + Serial.println(F("RTC is NOT running!")); return; // following line sets the RTC to the date & time this sketch was compiled // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); @@ -108,13 +191,22 @@ void setup() { // January 21, 2014 at 3am you would call: // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); } - Serial.print(F("DateTime::now ")); - printNow(&Serial); +#endif // RTC_TYPE + while (true) { + Serial.print(F("DateTime::now ")); + printNow(&Serial); + Serial.println(); + clearSerialInput(); + Serial.println(F("Type Y to set RTC, any other character to continue")); + while (!Serial.available()) {} + if (Serial.read() != 'Y') break; + if (setRtc()) break; + } Serial.println(); // Set callback FsDateTime::setCallback(dateTime); - + if (!sd.begin(SD_CONFIG)) { sd.initErrorHalt(&Serial); } @@ -130,7 +222,7 @@ void setup() { file.print(F("Test file at: ")); printNow(&file); file.println(); - + file.close(); // List files in SD root. sd.ls(LS_DATE | LS_SIZE); diff --git a/examples/STM32Test/STM32Test.ino b/examples/STM32Test/STM32Test.ino index f56b7f1b..860e89d2 100644 --- a/examples/STM32Test/STM32Test.ino +++ b/examples/STM32Test/STM32Test.ino @@ -7,7 +7,7 @@ #include "FreeStack.h" // Chip select PA4, shared SPI, 18 MHz, port 1. -#define SD1_CONFIG SdSpiConfig(PA4, SHARED_SPI, SD_SCK_MHZ(18), &SPI) +#define SD1_CONFIG SdSpiConfig(PA4, SHARED_SPI, SD_SCK_MHZ(18), &SPI) SdFs sd1; FsFile file1; @@ -36,7 +36,7 @@ void errorHalt() { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -65,7 +65,7 @@ void setup() { } // Make Dir1 the working directory on sd1. if (!sd1.chdir("Dir1")) { - error("dsd1.chdir"); + error("dsd1.chdir"); } // initialize the second card if (!sd2.begin(SD2_CONFIG)) { @@ -79,8 +79,8 @@ void setup() { } // Make Dir2 the working directory on sd2. if (!sd2.chdir("Dir2")) { - error("sd2.chdir"); - } + error("sd2.chdir"); + } // remove test.bin from /Dir1 directory of sd1 if (sd1.exists("test.bin")) { if (!sd1.remove("test.bin")) { @@ -144,7 +144,7 @@ void setup() { // close test.bin file1.close(); // sync copy.bin so ls works. - file2.close(); + file2.close(); // list directories. Serial.println(F("------sd1 -------")); sd1.ls("/", LS_R | LS_SIZE); diff --git a/examples/SdFormatter/SdFormatter.ino b/examples/SdFormatter/SdFormatter.ino index ea06ccdb..f20a1726 100644 --- a/examples/SdFormatter/SdFormatter.ino +++ b/examples/SdFormatter/SdFormatter.ino @@ -73,6 +73,15 @@ void sdErrorHalt() { SysCall::halt(); } //------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} +//------------------------------------------------------------------------------ // flash erase all data uint32_t const ERASE_SIZE = 262144L; void eraseCard() { @@ -154,9 +163,8 @@ void setup() { SysCall::yield(); } // Discard any extra characters. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); + cout << F( "\n" "This program can erase and/or format SD/SDHC/SDXC cards.\n" @@ -181,9 +189,7 @@ void setup() { return; } // Read any existing Serial data. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); // Select and initialize proper card driver. m_card = cardFactory.newCard(SD_CONFIG); diff --git a/examples/SdInfo/SdInfo.ino b/examples/SdInfo/SdInfo.ino index c03fee85..d326ba66 100644 --- a/examples/SdInfo/SdInfo.ino +++ b/examples/SdInfo/SdInfo.ino @@ -59,6 +59,15 @@ bool cidDmp() { return true; } //------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} +//------------------------------------------------------------------------------ bool csdDmp() { bool eraseSingleBlock; if (m_csd.v1.csd_ver == 0) { @@ -206,9 +215,7 @@ void setup() { //------------------------------------------------------------------------------ void loop() { // Read any existing Serial data. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); // F stores strings in flash to save RAM cout << F("\ntype any character to start\n"); diff --git a/examples/SoftwareSpi/SoftwareSpi.ino b/examples/SoftwareSpi/SoftwareSpi.ino index d6cdf31c..b7a753f0 100644 --- a/examples/SoftwareSpi/SoftwareSpi.ino +++ b/examples/SoftwareSpi/SoftwareSpi.ino @@ -41,7 +41,7 @@ FsFile file; void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -60,7 +60,7 @@ void setup() { file.println(F("This line was printed using software SPI.")); file.rewind(); - + while (file.available()) { Serial.write(file.read()); } diff --git a/examples/TeensyRtcTimestamp/TeensyRtcTimestamp.ino b/examples/TeensyRtcTimestamp/TeensyRtcTimestamp.ino index 02025c7b..d122a450 100644 --- a/examples/TeensyRtcTimestamp/TeensyRtcTimestamp.ino +++ b/examples/TeensyRtcTimestamp/TeensyRtcTimestamp.ino @@ -9,7 +9,7 @@ #define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and - your hardware does not use the default value, SS. + your hardware does not use the default value, SS. Common values are: Arduino Ethernet shield: pin 4 Sparkfun SD shield: pin 8 @@ -52,13 +52,13 @@ FsFile file; //------------------------------------------------------------------------------ // Call back for file timestamps. Only called for file create and sync(). void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) { - + // Return date using FS_DATE macro to format fields. *date = FS_DATE(year(), month(), day()); // Return time using FS_TIME macro to format fields. *time = FS_TIME(hour(), minute(), second()); - + // Return low time bits in units of 10 ms. *ms10 = second() & 1 ? 100 : 0; } @@ -71,17 +71,17 @@ time_t getTeensy3Time() void printField(Print* pr, char sep, uint8_t v) { if (sep) { pr->write(sep); - } + } if (v < 10) { pr->write('0'); } pr->print(v); } -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ void printNow(Print* pr) { pr->print(year()); printField(pr, '-', month()); - printField(pr, '-', day()); + printField(pr, '-', day()); printField(pr, ' ', hour()); printField(pr, ':', minute()); printField(pr, ':', second()); @@ -90,7 +90,7 @@ void printNow(Print* pr) { void setup() { // set the Time library to use Teensy 3.0's RTC to keep time setSyncProvider(getTeensy3Time); - + Serial.begin(9600); while (!Serial) { yield(); @@ -109,7 +109,7 @@ void setup() { // Set callback FsDateTime::setCallback(dateTime); - + if (!sd.begin(SD_CONFIG)) { sd.initErrorHalt(&Serial); } @@ -125,7 +125,7 @@ void setup() { file.print(F("Test file at: ")); printNow(&file); file.println(); - + file.close(); // List files in SD root. sd.ls(LS_DATE | LS_SIZE); diff --git a/examples/TeensySdioDemo/TeensySdioDemo.ino b/examples/TeensySdioDemo/TeensySdioDemo.ino index 637a140f..652086c8 100644 --- a/examples/TeensySdioDemo/TeensySdioDemo.ino +++ b/examples/TeensySdioDemo/TeensySdioDemo.ino @@ -52,6 +52,15 @@ uint32_t yieldCalls = 0; // Max busy time for single yield call. uint32_t yieldMaxUsec = 0; //------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} +//------------------------------------------------------------------------------ void errorHalt(const char* msg) { Serial.print("Error: "); Serial.println(msg); @@ -63,7 +72,7 @@ void errorHalt(const char* msg) { Serial.print(", ErrorData: 0X"); Serial.println(sd.sdErrorData(), HEX); } - while (true) {} + while (true) {} } bool ready = false; //------------------------------------------------------------------------------ @@ -94,14 +103,14 @@ void runTest() { totalMicros = 0; yieldMicros = 0; yieldCalls = 0; - yieldMaxUsec = 0; + yieldMaxUsec = 0; if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT)) { errorHalt("open failed"); } Serial.println("\nsize,write,read"); Serial.println("bytes,KB/sec,KB/sec"); for (size_t nb = 512; nb <= BUF_DIM; nb *= 2) { - uint32_t nRdWr = FILE_SIZE/nb; + uint32_t nRdWr = FILE_SIZE/nb; if (!file.truncate(0)) { errorHalt("truncate failed"); } @@ -123,19 +132,19 @@ void runTest() { Serial.print(','); file.rewind(); t = micros(); - + for (uint32_t n = 0; n < nRdWr; n++) { if ((int)nb != file.read(buf, nb)) { errorHalt("read failed"); } - // crude check of data. + // crude check of data. if (buf32[0] != n || buf32[nb/4 - 1] != n) { errorHalt("data check"); } } t = micros() - t; - totalMicros += t; - Serial.println(1000.0*FILE_SIZE/t); + totalMicros += t; + Serial.println(1000.0*FILE_SIZE/t); } file.close(); Serial.print("\ntotalMicros "); @@ -145,7 +154,7 @@ void runTest() { Serial.print("yieldCalls "); Serial.println(yieldCalls); Serial.print("yieldMaxUsec "); - Serial.println(yieldMaxUsec); + Serial.println(yieldMaxUsec); // Serial.print("kHzSdClk "); // Serial.println(kHzSdClk()); Serial.println("Done"); @@ -166,9 +175,7 @@ void loop() { "SPI mode so do SDIO tests first.\n" "\nCycle power on the card if an error occurs."); } - do { - delay(10); - } while (Serial.available() && Serial.read()); + clearSerialInput(); Serial.println( "\nType '1' for FIFO SDIO" @@ -198,7 +205,7 @@ void loop() { if (!sd.begin(SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(50)))) { errorHalt("begin failed"); } - Serial.println("\nShared SPI mode - slow for small transfers."); + Serial.println("\nShared SPI mode - slow for small transfers."); } else { Serial.println("Invalid input"); return; diff --git a/examples/UserChipSelectFunction/UserChipSelectFunction.ino b/examples/UserChipSelectFunction/UserChipSelectFunction.ino index 3d31b7c2..57376d3b 100644 --- a/examples/UserChipSelectFunction/UserChipSelectFunction.ino +++ b/examples/UserChipSelectFunction/UserChipSelectFunction.ino @@ -5,7 +5,7 @@ // SD_CHIP_SELECT_MODE must be set to one or two in SdFat/SdFatConfig.h. // A value of one allows optional replacement and two requires replacement. -#if SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2 +#if SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2 // SD chip select pin. #define SD_CS_PIN SS @@ -34,11 +34,11 @@ void setup() { sd.initErrorHalt(&Serial); } sd.ls(&Serial, LS_SIZE); - + Serial.print(F("sdCsInit calls: ")); Serial.println(initCalls); Serial.print(F("sdCsWrite calls: ")); - Serial.println(writeCalls); + Serial.println(writeCalls); } //------------------------------------------------------------------------------ void loop() {} diff --git a/examples/UserSPIDriver/UserSPIDriver.ino b/examples/UserSPIDriver/UserSPIDriver.ino index e2ada605..1317c85c 100644 --- a/examples/UserSPIDriver/UserSPIDriver.ino +++ b/examples/UserSPIDriver/UserSPIDriver.ino @@ -21,7 +21,7 @@ class MySpiClass : public SdSpiBaseClass { } // Initialize the SPI bus. void begin(SdSpiConfig config) { - (void)config; + (void)config; SPI.begin(); } // Deactivate SPI hardware. @@ -32,7 +32,7 @@ class MySpiClass : public SdSpiBaseClass { uint8_t receive() { return SPI.transfer(0XFF); } - // Receive multiple bytes. + // Receive multiple bytes. // Replace this function if your board has multiple byte receive. uint8_t receive(uint8_t* buf, size_t count) { for (size_t i = 0; i < count; i++) { diff --git a/examples/bench/bench.ino b/examples/bench/bench.ino index 356da4a1..c3b1524a 100644 --- a/examples/bench/bench.ino +++ b/examples/bench/bench.ino @@ -108,6 +108,15 @@ void cidDmp() { cout << endl; } //------------------------------------------------------------------------------ +void clearSerialInput() { + uint32_t m = micros(); + do { + if (Serial.read() >= 0) { + m = micros(); + } + } while (micros() - m < 10000); +} +//------------------------------------------------------------------------------ void setup() { Serial.begin(9600); @@ -122,7 +131,6 @@ void setup() { "\nSet ENABLE_DEDICATED_SPI nonzero in\n" "SdFatConfig.h for best SPI performance.\n"); } - // use uppercase in hex and use 0X base prefix cout << uppercase << showbase << endl; } @@ -136,9 +144,7 @@ void loop() { bool skipLatency; // Discard any input. - do { - delay(10); - } while (Serial.available() && Serial.read() >= 0); + clearSerialInput(); // F() stores strings in flash to save RAM cout << F("Type any character to start\n"); diff --git a/examples/examplesV1/#attic/AnalogLogger/AnalogLogger.ino b/examples/examplesV1/#attic/AnalogLogger/AnalogLogger.ino index 5e1f9654..11b5f3ed 100644 --- a/examples/examplesV1/#attic/AnalogLogger/AnalogLogger.ino +++ b/examples/examplesV1/#attic/AnalogLogger/AnalogLogger.ino @@ -66,7 +66,7 @@ ostream& operator << (ostream& os, DateTime& dt) { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - + // Wait for USB Serial. while (!Serial) { SysCall::yield(); diff --git a/examples/examplesV1/#attic/BaseExtCaseTest/BaseExtCaseTest.ino b/examples/examplesV1/#attic/BaseExtCaseTest/BaseExtCaseTest.ino index 0212d3ba..9d6b1b5f 100644 --- a/examples/examplesV1/#attic/BaseExtCaseTest/BaseExtCaseTest.ino +++ b/examples/examplesV1/#attic/BaseExtCaseTest/BaseExtCaseTest.ino @@ -17,8 +17,8 @@ const char* name[] = { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/HelloWorld/HelloWorld.ino b/examples/examplesV1/#attic/HelloWorld/HelloWorld.ino index 2f168036..8a92300e 100644 --- a/examples/examplesV1/#attic/HelloWorld/HelloWorld.ino +++ b/examples/examplesV1/#attic/HelloWorld/HelloWorld.ino @@ -8,7 +8,7 @@ ArduinoOutStream cout(Serial); void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino b/examples/examplesV1/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino index f727d2d4..710ac412 100644 --- a/examples/examplesV1/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino +++ b/examples/examplesV1/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino @@ -24,8 +24,8 @@ void error(const char* s) { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { yield(); } @@ -51,7 +51,7 @@ void loop() { if (!SD.begin(chipSelect)) { error("begin"); } - + Serial.println(F("Starting print test. Please wait.\n")); // do write test diff --git a/examples/examplesV1/#attic/SD_Size/SD_Size.ino b/examples/examplesV1/#attic/SD_Size/SD_Size.ino index b021d276..fc82dc63 100644 --- a/examples/examplesV1/#attic/SD_Size/SD_Size.ino +++ b/examples/examplesV1/#attic/SD_Size/SD_Size.ino @@ -9,8 +9,8 @@ File file; //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { yield(); } diff --git a/examples/examplesV1/#attic/SdFatSize/SdFatSize.ino b/examples/examplesV1/#attic/SdFatSize/SdFatSize.ino index 3c37d306..c84664d3 100644 --- a/examples/examplesV1/#attic/SdFatSize/SdFatSize.ino +++ b/examples/examplesV1/#attic/SdFatSize/SdFatSize.ino @@ -12,12 +12,12 @@ SdFile file; //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } - + if (!sd.begin()) { Serial.println("begin failed"); return; diff --git a/examples/examplesV1/#attic/StreamParseInt/StreamParseInt.ino b/examples/examplesV1/#attic/StreamParseInt/StreamParseInt.ino index 2da1f7c6..56623e55 100644 --- a/examples/examplesV1/#attic/StreamParseInt/StreamParseInt.ino +++ b/examples/examplesV1/#attic/StreamParseInt/StreamParseInt.ino @@ -17,7 +17,7 @@ void setup() { } Serial.println(F("Type any character to start")); while (!Serial.available()) { - SysCall::yield(); + SysCall::yield(); } // Initialize the SD. if (!SD.begin(csPin)) { diff --git a/examples/examplesV1/#attic/append/append.ino b/examples/examplesV1/#attic/append/append.ino index cd2915d9..282668bd 100644 --- a/examples/examplesV1/#attic/append/append.ino +++ b/examples/examplesV1/#attic/append/append.ino @@ -26,8 +26,8 @@ void setup() { char name[] = "append.txt"; Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/average/average.ino b/examples/examplesV1/#attic/average/average.ino index 22126b46..eaa3d2da 100644 --- a/examples/examplesV1/#attic/average/average.ino +++ b/examples/examplesV1/#attic/average/average.ino @@ -55,8 +55,8 @@ void calcAverage() { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/benchSD/benchSD.ino b/examples/examplesV1/#attic/benchSD/benchSD.ino index 315548d2..f0609490 100644 --- a/examples/examplesV1/#attic/benchSD/benchSD.ino +++ b/examples/examplesV1/#attic/benchSD/benchSD.ino @@ -27,8 +27,8 @@ void error(const char* s) { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { yield(); } @@ -46,7 +46,7 @@ void loop() { // F() stores strings in flash to save RAM Serial.println(F("Type any character to start")); - + while (!Serial.available()) { yield(); } diff --git a/examples/examplesV1/#attic/bufstream/bufstream.ino b/examples/examplesV1/#attic/bufstream/bufstream.ino index eb029d82..27b00dd5 100644 --- a/examples/examplesV1/#attic/bufstream/bufstream.ino +++ b/examples/examplesV1/#attic/bufstream/bufstream.ino @@ -13,8 +13,8 @@ void setup() { int i, j, k; // values from parsed line Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/cin_cout/cin_cout.ino b/examples/examplesV1/#attic/cin_cout/cin_cout.ino index 466895b4..5f8d72d8 100644 --- a/examples/examplesV1/#attic/cin_cout/cin_cout.ino +++ b/examples/examplesV1/#attic/cin_cout/cin_cout.ino @@ -16,7 +16,7 @@ ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf)); //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/eventlog/eventlog.ino b/examples/examplesV1/#attic/eventlog/eventlog.ino index 9065f315..31bad67a 100644 --- a/examples/examplesV1/#attic/eventlog/eventlog.ino +++ b/examples/examplesV1/#attic/eventlog/eventlog.ino @@ -36,7 +36,7 @@ void logEvent(const char *msg) { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/fgetsRewrite/fgetsRewrite.ino b/examples/examplesV1/#attic/fgetsRewrite/fgetsRewrite.ino index 159445e0..05a9caac 100644 --- a/examples/examplesV1/#attic/fgetsRewrite/fgetsRewrite.ino +++ b/examples/examplesV1/#attic/fgetsRewrite/fgetsRewrite.ino @@ -86,8 +86,8 @@ void makeTestFile() { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/#attic/readlog/readlog.ino b/examples/examplesV1/#attic/readlog/readlog.ino index b5eb8384..28522f98 100644 --- a/examples/examplesV1/#attic/readlog/readlog.ino +++ b/examples/examplesV1/#attic/readlog/readlog.ino @@ -18,8 +18,8 @@ ArduinoOutStream cout(Serial); void setup() { int c; Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/LowLatencyLoggerADXL345/UserFunctions.cpp b/examples/examplesV1/LowLatencyLoggerADXL345/UserFunctions.cpp index 71d624f6..14df7c06 100644 --- a/examples/examplesV1/LowLatencyLoggerADXL345/UserFunctions.cpp +++ b/examples/examplesV1/LowLatencyLoggerADXL345/UserFunctions.cpp @@ -17,12 +17,12 @@ const uint8_t DATAZ1 = 0x37; //Z-Axis Data 1 void writeADXL345Register(const uint8_t registerAddress, const uint8_t value) { // Max SPI clock frequency is 5 MHz with CPOL = 1 and CPHA = 1. - SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3)); + SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3)); digitalWrite(ADXL345_CS, LOW); SPI.transfer(registerAddress); SPI.transfer(value); digitalWrite(ADXL345_CS, HIGH); - SPI.endTransaction(); + SPI.endTransaction(); } void userSetup() { @@ -32,7 +32,7 @@ void userSetup() { //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register. writeADXL345Register(DATA_FORMAT, 0x01); //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register. - writeADXL345Register(POWER_CTL, 0x08); //Measurement mode + writeADXL345Register(POWER_CTL, 0x08); //Measurement mode } // Acquire a data record. @@ -45,7 +45,7 @@ void acquireData(data_t* data) { SPI.transfer(DATAX0 | 0XC0); data->accel[0] = SPI.transfer(0) | (SPI.transfer(0) << 8); data->accel[1] = SPI.transfer(0) | (SPI.transfer(0) << 8); - data->accel[2] = SPI.transfer(0) | (SPI.transfer(0) << 8); + data->accel[2] = SPI.transfer(0) | (SPI.transfer(0) << 8); digitalWrite(ADXL345_CS, HIGH); SPI.endTransaction(); } diff --git a/examples/examplesV1/LowLatencyLoggerMPU6050/UserFunctions.cpp b/examples/examplesV1/LowLatencyLoggerMPU6050/UserFunctions.cpp index 606a40d6..38333186 100644 --- a/examples/examplesV1/LowLatencyLoggerMPU6050/UserFunctions.cpp +++ b/examples/examplesV1/LowLatencyLoggerMPU6050/UserFunctions.cpp @@ -9,7 +9,7 @@ static uint32_t startMicros; // Acquire a data record. void acquireData(data_t* data) { data->time = micros(); - mpu.getMotion6(&data->ax, &data->ay, &data->az, + mpu.getMotion6(&data->ax, &data->ay, &data->az, &data->gx, &data->gy, &data->gz); } @@ -21,7 +21,7 @@ void userSetup() { #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif - mpu.initialize(); + mpu.initialize(); } // Print a data record. diff --git a/examples/examplesV1/OpenNext/OpenNext.ino b/examples/examplesV1/OpenNext/OpenNext.ino index d88a49d9..542203fb 100644 --- a/examples/examplesV1/OpenNext/OpenNext.ino +++ b/examples/examplesV1/OpenNext/OpenNext.ino @@ -15,12 +15,12 @@ SdFile file; //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } - + Serial.println("Type any character to start"); while (!Serial.available()) { SysCall::yield(); diff --git a/examples/examplesV1/PrintBenchmark/PrintBenchmark.ino b/examples/examplesV1/PrintBenchmark/PrintBenchmark.ino index d7cc68d4..c475e193 100644 --- a/examples/examplesV1/PrintBenchmark/PrintBenchmark.ino +++ b/examples/examplesV1/PrintBenchmark/PrintBenchmark.ino @@ -26,7 +26,7 @@ ArduinoOutStream cout(Serial); //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/RawWrite/RawWrite.ino b/examples/examplesV1/RawWrite/RawWrite.ino index 9d57ede3..d3633d21 100644 --- a/examples/examplesV1/RawWrite/RawWrite.ino +++ b/examples/examplesV1/RawWrite/RawWrite.ino @@ -45,8 +45,8 @@ ArduinoOutStream cout(Serial); //------------------------------------------------------------------------------ void setup(void) { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -101,7 +101,7 @@ void loop(void) { cout << F("Start raw write of ") << file.fileSize()/1000UL << F(" KB\n"); cout << F("Target rate: ") << RATE_KB_PER_SEC << F(" KB/sec\n"); cout << F("Target time: ") << TEST_TIME_SEC << F(" seconds\n"); - + // tell card to setup for multiple block write with pre-erase if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) { error("writeStart failed"); @@ -173,7 +173,7 @@ void loop(void) { cout << F(" seconds\n"); cout << F("Min block write time: ") << minWriteTime << F(" micros\n"); cout << F("Max block write time: ") << maxWriteTime << F(" micros\n"); - cout << F("Avg block write time: ") << avgWriteTime << F(" micros\n"); + cout << F("Avg block write time: ") << avgWriteTime << F(" micros\n"); // close file for next pass of loop file.close(); Serial.println(); diff --git a/examples/examplesV1/ReadCsv/ReadCsv.ino b/examples/examplesV1/ReadCsv/ReadCsv.ino index d57aadf4..9527a0e8 100644 --- a/examples/examplesV1/ReadCsv/ReadCsv.ino +++ b/examples/examplesV1/ReadCsv/ReadCsv.ino @@ -30,7 +30,7 @@ File file; * delim - csv delimiter. * * return - negative value for failure. - * delimiter, '\n' or zero(EOF) for success. + * delimiter, '\n' or zero(EOF) for success. */ int csvReadText(File* file, char* str, size_t size, char delim) { char ch; @@ -129,8 +129,8 @@ int csvReadFloat(File* file, float* num, char delim) { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { yield(); } @@ -144,8 +144,8 @@ void setup() { return; } // Remove existing file. - SD.remove("READTEST.TXT"); - + SD.remove("READTEST.TXT"); + // Create the file. file = SD.open("READTEST.TXT", FILE_WRITE); if (!file) { @@ -169,7 +169,7 @@ void setup() { file.seek(0); // Read the file and print fields. - int16_t tcalc; + int16_t tcalc; float t1, t2, h1, h2; // Must be dim 9 to allow for zero byte. char timeS[9], dateS[9]; @@ -188,7 +188,7 @@ void setup() { while ((ch = file.read()) > 0 && nr++ < 100) { Serial.write(ch); } - break; + break; } Serial.print(tcalc); Serial.print(CSV_DELIM); diff --git a/examples/examplesV1/ReadCsvArray/ReadCsvArray.ino b/examples/examplesV1/ReadCsvArray/ReadCsvArray.ino index b837a89f..ea0e922c 100644 --- a/examples/examplesV1/ReadCsvArray/ReadCsvArray.ino +++ b/examples/examplesV1/ReadCsvArray/ReadCsvArray.ino @@ -51,8 +51,8 @@ size_t readField(File* file, char* str, size_t size, const char* delim) { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -63,7 +63,7 @@ void setup() { // Initialize the SD. if (!SD.begin(CS_PIN)) { errorHalt("begin failed"); - } + } // Create or open the file. file = SD.open("READNUM.TXT", FILE_WRITE); if (!file) { @@ -93,7 +93,7 @@ void setup() { char *ptr; // Test for valid field. // Read the file and store the data. - + for (i = 0; i < ROW_DIM; i++) { for (j = 0; j < COL_DIM; j++) { n = readField(&file, str, sizeof(str), ",\n"); @@ -117,7 +117,7 @@ void setup() { // Allow missing endl at eof. if (str[n-1] != '\n' && file.available()) { errorHalt("missing endl"); - } + } } // Print the array. diff --git a/examples/examplesV1/ReadCsvStream/ReadCsvStream.ino b/examples/examplesV1/ReadCsvStream/ReadCsvStream.ino index 47238e59..4e89b67c 100644 --- a/examples/examplesV1/ReadCsvStream/ReadCsvStream.ino +++ b/examples/examplesV1/ReadCsvStream/ReadCsvStream.ino @@ -92,14 +92,14 @@ void writeFile() { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } cout << F("Type any character to start\n"); while (!Serial.available()) { - SysCall::yield(); + SysCall::yield(); } // Initialize at the highest speed supported by the board that is diff --git a/examples/examplesV1/STM32Test/STM32Test.ino b/examples/examplesV1/STM32Test/STM32Test.ino index 91da7892..5e1a94b2 100644 --- a/examples/examplesV1/STM32Test/STM32Test.ino +++ b/examples/examplesV1/STM32Test/STM32Test.ino @@ -33,7 +33,7 @@ const uint16_t NWRITE = FILE_SIZE/BUF_DIM; //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { } @@ -151,7 +151,7 @@ void setup() { Serial.println(F(" millis")); // close test.bin file1.close(); - file2.close(); + file2.close(); // list current directory on both cards Serial.println(F("------sd1 -------")); sd1.ls("/", LS_R | LS_DATE | LS_SIZE); diff --git a/examples/examplesV1/SdFormatter/SdFormatter.ino b/examples/examplesV1/SdFormatter/SdFormatter.ino index 2a3a0410..570d9820 100644 --- a/examples/examplesV1/SdFormatter/SdFormatter.ino +++ b/examples/examplesV1/SdFormatter/SdFormatter.ino @@ -12,7 +12,7 @@ * and SDFormatter uses FAT12. */ #error use new Version 2 SdFormatter -// Set USE_SDIO to zero for SPI card access. +// Set USE_SDIO to zero for SPI card access. #define USE_SDIO 0 // // Change the value of chipSelect if your hardware does @@ -45,7 +45,7 @@ SdioCardEX card; #else // USE_SDIO Sd2Card card; #endif // USE_SDIO - + uint32_t cardSizeBlocks; uint32_t cardCapacityMB; @@ -171,10 +171,10 @@ void clearFatDir(uint32_t bgn, uint32_t count) { for (uint32_t i = 0; i < count; i++) { if (!card.writeBlock(bgn + i, cache.data)) { sdError("Clear FAT/DIR writeBlock failed"); - } + } if ((i & 0XFF) == 0) { cout << '.'; - } + } } #else // USE_SDIO if (!card.writeStart(bgn, count)) { @@ -461,7 +461,7 @@ void formatCard() { void setup() { char c; Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -521,7 +521,7 @@ void setup() { } #if USE_SDIO if (!card.begin()) { - sdError("card.begin failed"); + sdError("card.begin failed"); } #else // USE_SDIO if (!card.begin(chipSelect, SPI_SPEED)) { @@ -531,7 +531,7 @@ void setup() { "Is chip select correct at the top of this program?\n"); sdError("card.begin failed"); } -#endif +#endif cardSizeBlocks = card.cardSize(); if (cardSizeBlocks == 0) { sdError("cardSize"); diff --git a/examples/examplesV1/SdInfo/SdInfo.ino b/examples/examplesV1/SdInfo/SdInfo.ino index 10306879..8549528f 100644 --- a/examples/examplesV1/SdInfo/SdInfo.ino +++ b/examples/examplesV1/SdInfo/SdInfo.ino @@ -5,7 +5,7 @@ #include "SdFat.h" #include "sdios.h" #error Use new Version 2 SdInfo -// Set USE_SDIO to zero for SPI card access. +// Set USE_SDIO to zero for SPI card access. #define USE_SDIO 0 /* * SD chip select pin. Common values are: @@ -143,8 +143,8 @@ void volDmp() { //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -154,7 +154,7 @@ void setup() { // F stores strings in flash to save RAM cout << F("SdFat version: ") << SD_FAT_VERSION << endl; -#if !USE_SDIO +#if !USE_SDIO if (DISABLE_CHIP_SELECT < 0) { cout << F( "\nAssuming the SD is the only SPI device.\n" @@ -167,7 +167,7 @@ void setup() { } cout << F("\nAssuming the SD chip select pin is: ") <cardSize(); diff --git a/examples/examplesV1/SoftwareSpi/SoftwareSpi.ino b/examples/examplesV1/SoftwareSpi/SoftwareSpi.ino index babd4151..a3907939 100644 --- a/examples/examplesV1/SoftwareSpi/SoftwareSpi.ino +++ b/examples/examplesV1/SoftwareSpi/SoftwareSpi.ino @@ -24,7 +24,7 @@ SdFile file; void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -43,7 +43,7 @@ void setup() { file.println(F("This line was printed using software SPI.")); file.rewind(); - + while (file.available()) { Serial.write(file.read()); } diff --git a/examples/examplesV1/StdioBench/StdioBench.ino b/examples/examplesV1/StdioBench/StdioBench.ino index f4412a3e..9412d628 100644 --- a/examples/examplesV1/StdioBench/StdioBench.ino +++ b/examples/examplesV1/StdioBench/StdioBench.ino @@ -42,7 +42,7 @@ void setup() { Serial.println(F("Starting test")); // Initialize at the highest speed supported by the board that is - // not over 50 MHz. Try a lower speed if SPI errors occur. + // not over 50 MHz. Try a lower speed if SPI errors occur. if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) { sd.errorHalt(); } @@ -146,7 +146,7 @@ void setup() { stdioFile.printField(n, '\n'); #else // PRINT_FIELD stdioFile.println(n); -#endif // PRINT_FIELD +#endif // PRINT_FIELD } break; @@ -157,7 +157,7 @@ void setup() { stdioFile.printField(f[i], '\n', 4); #else // PRINT_FIELD stdioFile.println(f[i], 4); -#endif // PRINT_FIELD +#endif // PRINT_FIELD } } break; diff --git a/examples/examplesV1/TeensySdioDemo/TeensySdioDemo.ino b/examples/examplesV1/TeensySdioDemo/TeensySdioDemo.ino index 7fcdb01b..1c5214f4 100644 --- a/examples/examplesV1/TeensySdioDemo/TeensySdioDemo.ino +++ b/examples/examplesV1/TeensySdioDemo/TeensySdioDemo.ino @@ -1,7 +1,7 @@ // Simple performance test for Teensy 3.5/3.6 SDHC. // Demonstrates yield() efficiency. -// Warning SdFatSdio and SdFatSdioEX normally should +// Warning SdFatSdio and SdFatSdioEX normally should // not both be used in a program. // Each has its own cache and member variables. @@ -48,8 +48,8 @@ void errorHalt(const char* msg) { } //------------------------------------------------------------------------------ uint32_t kHzSdClk() { - return useEx ? sdEx.card()->kHzSdClk() : sd.card()->kHzSdClk(); -} + return useEx ? sdEx.card()->kHzSdClk() : sd.card()->kHzSdClk(); +} //------------------------------------------------------------------------------ // Replace "weak" system yield() function. void yield() { @@ -74,7 +74,7 @@ void runTest() { totalMicros = 0; yieldMicros = 0; yieldCalls = 0; - yieldMaxUsec = 0; + yieldMaxUsec = 0; if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT)) { errorHalt("open failed"); } @@ -100,19 +100,19 @@ void runTest() { Serial.print(','); file.rewind(); t = micros(); - + for (uint32_t n = 0; n < nRdWr; n++) { if ((int)nb != file.read(buf, nb)) { errorHalt("read failed"); } - // crude check of data. + // crude check of data. if (buf32[0] != n || buf32[nb/4 - 1] != n) { errorHalt("data check"); } } t = micros() - t; - totalMicros += t; - Serial.println(1000.0*FILE_SIZE/t); + totalMicros += t; + Serial.println(1000.0*FILE_SIZE/t); } file.close(); Serial.print("\ntotalMicros "); @@ -122,7 +122,7 @@ void runTest() { Serial.print("yieldCalls "); Serial.println(yieldCalls); Serial.print("yieldMaxUsec "); - Serial.println(yieldMaxUsec); + Serial.println(yieldMaxUsec); Serial.print("kHzSdClk "); Serial.println(kHzSdClk()); Serial.println("Done"); @@ -133,8 +133,8 @@ void setup() { while (!Serial) { } Serial.println("SdFatSdioEX uses extended multi-block transfers without DMA."); - Serial.println("SdFatSdio uses a traditional DMA SDIO implementation."); - Serial.println("Note the difference is speed and busy yield time.\n"); + Serial.println("SdFatSdio uses a traditional DMA SDIO implementation."); + Serial.println("Note the difference is speed and busy yield time.\n"); } //----------------------------------------------------------------------------- void loop() { @@ -163,7 +163,7 @@ void loop() { sd.initErrorHalt("SdFatSdio begin() failed"); } // make sd the current volume. - sd.chvol(); + sd.chvol(); } runTest(); } \ No newline at end of file diff --git a/examples/examplesV1/Timestamp/Timestamp.ino b/examples/examplesV1/Timestamp/Timestamp.ino index 61d2bdcd..19b232cd 100644 --- a/examples/examplesV1/Timestamp/Timestamp.ino +++ b/examples/examplesV1/Timestamp/Timestamp.ino @@ -53,7 +53,7 @@ void dateTime(uint16_t* date, uint16_t* time) { void printTimestamps(SdFile& f) { cout << F("Creation: "); f.printCreateDateTime(&Serial); - cout << endl << F("Modify: "); + cout << endl << F("Modify: "); f.printModifyDateTime(&Serial); cout << endl << F("Access: "); f.printAccessDateTime(&Serial); @@ -68,7 +68,7 @@ void setup(void) { } cout << F("Type any character to start\n"); while (!Serial.available()) { - SysCall::yield(); + SysCall::yield(); } // Initialize at the highest speed supported by the board that is // not over 50 MHz. Try a lower speed if SPI errors occur. diff --git a/examples/examplesV1/TwoCards/TwoCards.ino b/examples/examplesV1/TwoCards/TwoCards.ino index dc85e35e..79fe6548 100644 --- a/examples/examplesV1/TwoCards/TwoCards.ino +++ b/examples/examplesV1/TwoCards/TwoCards.ino @@ -25,7 +25,7 @@ const uint32_t NWRITE = FILE_SIZE/BUF_DIM; //------------------------------------------------------------------------------ void setup() { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -146,7 +146,7 @@ void setup() { Serial.println(F(" millis")); // close test.bin file1.close(); - file2.close(); + file2.close(); // list current directory on both cards Serial.println(F("------sd1 -------")); sd1.ls("/", LS_R | LS_DATE | LS_SIZE); diff --git a/examples/examplesV1/dataLogger/dataLogger.ino b/examples/examplesV1/dataLogger/dataLogger.ino index 665e77d6..69926fe9 100644 --- a/examples/examplesV1/dataLogger/dataLogger.ino +++ b/examples/examplesV1/dataLogger/dataLogger.ino @@ -67,8 +67,8 @@ void setup() { char fileName[13] = FILE_BASE_NAME "00.csv"; Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -78,7 +78,7 @@ void setup() { while (!Serial.available()) { SysCall::yield(); } - + // Initialize at the highest speed supported by the board that is // not over 50 MHz. Try a lower speed if SPI errors occur. if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { diff --git a/examples/examplesV1/fgets/fgets.ino b/examples/examplesV1/fgets/fgets.ino index c1b06a61..8d4a2451 100644 --- a/examples/examplesV1/fgets/fgets.ino +++ b/examples/examplesV1/fgets/fgets.ino @@ -61,8 +61,8 @@ void makeTestFile() { //------------------------------------------------------------------------------ void setup(void) { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/formatting/formatting.ino b/examples/examplesV1/formatting/formatting.ino index a2b937ff..90a43e48 100644 --- a/examples/examplesV1/formatting/formatting.ino +++ b/examples/examplesV1/formatting/formatting.ino @@ -43,7 +43,7 @@ void showDate(int m, int d, int y) { void setup(void) { Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/getline/getline.ino b/examples/examplesV1/getline/getline.ino index 89ede662..88c68a97 100644 --- a/examples/examplesV1/getline/getline.ino +++ b/examples/examplesV1/getline/getline.ino @@ -55,8 +55,8 @@ void testGetline() { //------------------------------------------------------------------------------ void setup(void) { Serial.begin(9600); - - // Wait for USB Serial + + // Wait for USB Serial while (!Serial) { SysCall::yield(); } diff --git a/examples/examplesV1/wipe/wipe.ino b/examples/examplesV1/wipe/wipe.ino index 1de3e89a..b6341417 100644 --- a/examples/examplesV1/wipe/wipe.ino +++ b/examples/examplesV1/wipe/wipe.ino @@ -9,7 +9,7 @@ SdFat sd; void setup() { int c; Serial.begin(9600); - // Wait for USB Serial + // Wait for USB Serial while (!Serial) { SysCall::yield(); } @@ -22,7 +22,7 @@ void setup() { sd.errorHalt("Quitting, you did not type 'Y'."); } // Initialize at the highest speed supported by the board that is - // not over 50 MHz. Try a lower speed if SPI errors occur. + // not over 50 MHz. Try a lower speed if SPI errors occur. if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } @@ -32,7 +32,7 @@ void setup() { } // Must reinitialize after wipe. // Initialize at the highest speed supported by the board that is - // not over 50 MHz. Try a lower speed if SPI errors occur. + // not over 50 MHz. Try a lower speed if SPI errors occur. if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.errorHalt("Second init failed."); } diff --git a/extras/cpplint.py b/extras/cpplint.py index 52cb7d0c..4a82bde4 100644 --- a/extras/cpplint.py +++ b/extras/cpplint.py @@ -51,12 +51,19 @@ import string import sys import unicodedata +import sysconfig + +try: + xrange # Python 2 +except NameError: + xrange = range # Python 3 _USAGE = """ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] [--counting=total|toplevel|detailed] [--root=subdir] [--linelength=digits] [--headers=x,y,...] + [--quiet] [file] ... The style guidelines this tries to follow are those in @@ -83,6 +90,9 @@ verbose=# Specify a number 0-5 to restrict errors to certain verbosity levels. + quiet + Don't print anything if no errors are found. + filter=-x,+y,... Specify a comma-separated list of category-filters to apply: only error messages whose category names pass the filters will be printed. @@ -114,12 +124,13 @@ ignored. Examples: - Assuming that src/.git exists, the header guard CPP variables for - src/chrome/browser/ui/browser.h are: + Assuming that top/src/.git exists (and cwd=top/src), the header guard + CPP variables for top/src/chrome/browser/ui/browser.h are: No flag => CHROME_BROWSER_UI_BROWSER_H_ --root=chrome => BROWSER_UI_BROWSER_H_ --root=chrome/browser => UI_BROWSER_H_ + --root=.. => SRC_CHROME_BROWSER_UI_BROWSER_H_ linelength=digits This is the allowed line length for the project. The default value is @@ -168,9 +179,9 @@ "linelength" allows to specify the allowed line length for the project. The "root" option is similar in function to the --root flag (see example - above). - - The "headers" option is similar in function to the --headers flag + above). Paths are relative to the directory of the CPPLINT.cfg. + + The "headers" option is similar in function to the --headers flag (see example above). CPPLINT.cfg has an effect on files in the same directory and all @@ -539,6 +550,7 @@ # The root directory used for deriving header guard CPP variable. # This is set by --root flag. _root = None +_root_debug = False # The allowed line length of files. # This is set by --linelength flag. @@ -563,7 +575,7 @@ def ProcessHppHeadersOption(val): # Automatically append to extensions list so it does not have to be set 2 times _valid_extensions.update(_hpp_headers) except ValueError: - PrintUsage('Header extensions must be comma seperated list.') + PrintUsage('Header extensions must be comma separated list.') def IsHeaderExtension(file_extension): return file_extension in _hpp_headers @@ -859,6 +871,7 @@ def __init__(self): self._filters_backup = self.filters[:] self.counting = 'total' # In what way are we counting errors? self.errors_by_category = {} # string to int dict storing error counts + self.quiet = False # Suppress non-error messagess? # output format: # "emacs" - format that emacs can parse (default) @@ -869,6 +882,12 @@ def SetOutputFormat(self, output_format): """Sets the output format for errors.""" self.output_format = output_format + def SetQuiet(self, quiet): + """Sets the module's quiet settings, and returns the previous setting.""" + last_quiet = self.quiet + self.quiet = quiet + return last_quiet + def SetVerboseLevel(self, level): """Sets the module's verbosity, and returns the previous setting.""" last_verbose_level = self.verbose_level @@ -950,6 +969,14 @@ def _SetOutputFormat(output_format): """Sets the module's output format.""" _cpplint_state.SetOutputFormat(output_format) +def _Quiet(): + """Return's the module's quiet setting.""" + return _cpplint_state.quiet + +def _SetQuiet(quiet): + """Set the module's quiet status, and return previous setting.""" + return _cpplint_state.SetQuiet(quiet) + def _VerboseLevel(): """Returns the module's verbosity setting.""" @@ -1356,7 +1383,7 @@ def FindNextMultiLineCommentEnd(lines, lineix): def RemoveMultiLineCommentsFromRange(lines, begin, end): """Clears a range of lines for multi-line comments.""" - # Having // dummy comments makes the lines non-empty, so we will not get + # Having // comments makes the lines non-empty, so we will not get # unnecessary blank line warnings later in the code. for i in range(begin, end): lines[i] = '/**/' @@ -1730,7 +1757,7 @@ def CheckForCopyright(filename, lines, error): """Logs an error if no Copyright message appears at the top of the file.""" # We'll say it should occur by line 10. Don't forget there's a - # dummy line at the front. + # placeholder line at the front. for line in xrange(1, min(len(lines), 11)): if re.search(r'Copyright', lines[line], re.I): break else: # means no copyright line was found @@ -1754,6 +1781,30 @@ def GetIndentLevel(line): else: return 0 +def PathSplitToList(path): + """Returns the path split into a list by the separator. + + Args: + path: An absolute or relative path (e.g. '/a/b/c/' or '../a') + + Returns: + A list of path components (e.g. ['a', 'b', 'c]). + """ + lst = [] + while True: + (head, tail) = os.path.split(path) + if head == path: # absolute paths end + lst.append(head) + break + if tail == path: # relative paths end + lst.append(tail) + break + + path = head + lst.append(tail) + + lst.reverse() + return lst def GetHeaderGuardCPPVariable(filename): """Returns the CPP variable that should be used as a header guard. @@ -1776,13 +1827,58 @@ def GetHeaderGuardCPPVariable(filename): fileinfo = FileInfo(filename) file_path_from_root = fileinfo.RepositoryName() - if _root: - suffix = os.sep - # On Windows using directory separator will leave us with - # "bogus escape error" unless we properly escape regex. - if suffix == '\\': - suffix += '\\' - file_path_from_root = re.sub('^' + _root + suffix, '', file_path_from_root) + + def FixupPathFromRoot(): + if _root_debug: + sys.stderr.write("\n_root fixup, _root = '%s', repository name = '%s'\n" + %(_root, fileinfo.RepositoryName())) + + # Process the file path with the --root flag if it was set. + if not _root: + if _root_debug: + sys.stderr.write("_root unspecified\n") + return file_path_from_root + + def StripListPrefix(lst, prefix): + # f(['x', 'y'], ['w, z']) -> None (not a valid prefix) + if lst[:len(prefix)] != prefix: + return None + # f(['a, 'b', 'c', 'd'], ['a', 'b']) -> ['c', 'd'] + return lst[(len(prefix)):] + + # root behavior: + # --root=subdir , lstrips subdir from the header guard + maybe_path = StripListPrefix(PathSplitToList(file_path_from_root), + PathSplitToList(_root)) + + if _root_debug: + sys.stderr.write(("_root lstrip (maybe_path=%s, file_path_from_root=%s," + + " _root=%s)\n") %(maybe_path, file_path_from_root, _root)) + + if maybe_path: + return os.path.join(*maybe_path) + + # --root=.. , will prepend the outer directory to the header guard + full_path = fileinfo.FullName() + root_abspath = os.path.abspath(_root) + + maybe_path = StripListPrefix(PathSplitToList(full_path), + PathSplitToList(root_abspath)) + + if _root_debug: + sys.stderr.write(("_root prepend (maybe_path=%s, full_path=%s, " + + "root_abspath=%s)\n") %(maybe_path, full_path, root_abspath)) + + if maybe_path: + return os.path.join(*maybe_path) + + if _root_debug: + sys.stderr.write("_root ignore, returning %s\n" %(file_path_from_root)) + + # --root=FAKE_DIR is ignored + return file_path_from_root + + file_path_from_root = FixupPathFromRoot() return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_' @@ -3187,8 +3283,8 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error): line = clean_lines.elided[linenum] # You shouldn't have spaces before your brackets, except maybe after - # 'delete []' or 'return []() {};' - if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line): + # 'delete []', 'return []() {};', or 'auto [abc, ...] = ...;'. + if Search(r'\w\s+\[', line) and not Search(r'(?:auto&?|delete|return)\s+\[', line): error(filename, linenum, 'whitespace/braces', 5, 'Extra space before [') @@ -3770,9 +3866,9 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error): # Block bodies should not be followed by a semicolon. Due to C++11 # brace initialization, there are more places where semicolons are - # required than not, so we use a whitelist approach to check these - # rather than a blacklist. These are the places where "};" should - # be replaced by just "}": + # required than not, so we explicitly list the allowed rules rather + # than listing the disallowed ones. These are the places where "};" + # should be replaced by just "}": # 1. Some flavor of block following closing parenthesis: # for (;;) {}; # while (...) {}; @@ -3828,11 +3924,11 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error): # - INTERFACE_DEF # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: # - # We implement a whitelist of safe macros instead of a blacklist of + # We implement a list of safe macros instead of a list of # unsafe macros, even though the latter appears less frequently in # google code and would have been easier to implement. This is because - # the downside for getting the whitelist wrong means some extra - # semicolons, while the downside for getting the blacklist wrong + # the downside for getting the allowed checks wrong means some extra + # semicolons, while the downside for getting disallowed checks wrong # would result in compile errors. # # In addition to macros, we also don't want to warn on @@ -4196,6 +4292,16 @@ def GetLineWidth(line): if unicodedata.east_asian_width(uc) in ('W', 'F'): width += 2 elif not unicodedata.combining(uc): + # Issue 337 + # https://mail.python.org/pipermail/python-list/2012-August/628809.html + if (sys.version_info.major, sys.version_info.minor) <= (3, 2): + # https://github.com/python/cpython/blob/2.7/Include/unicodeobject.h#L81 + is_wide_build = sysconfig.get_config_var("Py_UNICODE_SIZE") >= 4 + # https://github.com/python/cpython/blob/2.7/Objects/unicodeobject.c#L564 + is_low_surrogate = 0xDC00 <= ord(uc) <= 0xDFFF + if not is_wide_build and is_low_surrogate: + width -= 1 + width += 1 return width else: @@ -5018,19 +5124,19 @@ def CheckForNonConstReference(filename, clean_lines, linenum, # # We also accept & in static_assert, which looks like a function but # it's actually a declaration expression. - whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|' + allowed_functions = (r'(?:[sS]wap(?:<\w:+>)?|' r'operator\s*[<>][<>]|' r'static_assert|COMPILE_ASSERT' r')\s*\(') - if Search(whitelisted_functions, line): + if Search(allowed_functions, line): return elif not Search(r'\S+\([^)]*$', line): - # Don't see a whitelisted function on this line. Actually we + # Don't see an allowed function on this line. Actually we # didn't see any function name on this line, so this is likely a # multi-line parameter list. Try a bit harder to catch this case. for i in xrange(2): if (linenum > i and - Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])): + Search(allowed_functions, clean_lines.elided[linenum - i - 1])): return decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body @@ -5884,6 +5990,9 @@ def ProcessConfigOverrides(filename): if base_name: pattern = re.compile(val) if pattern.match(base_name): + if _cpplint_state.quiet: + # Suppress "Ignoring file" warning when using --quiet. + return False sys.stderr.write('Ignoring "%s": file excluded by "%s". ' 'File path component "%s" matches ' 'pattern "%s"\n' % @@ -5897,7 +6006,8 @@ def ProcessConfigOverrides(filename): sys.stderr.write('Line length must be numeric.') elif name == 'root': global _root - _root = val + # root directories are specified relative to CPPLINT.cfg dir. + _root = os.path.join(os.path.dirname(cfg_file), val) elif name == 'headers': ProcessHppHeadersOption(val) else: @@ -5934,6 +6044,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): _SetVerboseLevel(vlevel) _BackupFilters() + old_errors = _cpplint_state.error_count if not ProcessConfigOverrides(filename): _RestoreFilters() @@ -6002,7 +6113,10 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): Error(filename, linenum, 'whitespace/newline', 1, 'Unexpected \\r (^M) found; better to use only \\n') - sys.stdout.write('Done processing %s\n' % filename) + # Suppress printing anything if --quiet was passed unless the error + # count has increased after processing this file. + if not _cpplint_state.quiet or old_errors != _cpplint_state.error_count: + sys.stdout.write('Done processing %s\n' % filename) _RestoreFilters() @@ -6046,13 +6160,15 @@ def ParseArguments(args): 'root=', 'linelength=', 'extensions=', - 'headers=']) + 'headers=', + 'quiet']) except getopt.GetoptError: PrintUsage('Invalid arguments.') verbosity = _VerboseLevel() output_format = _OutputFormat() filters = '' + quiet = _Quiet() counting_style = '' for (opt, val) in opts: @@ -6062,6 +6178,8 @@ def ParseArguments(args): if val not in ('emacs', 'vs7', 'eclipse'): PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.') output_format = val + elif opt == '--quiet': + quiet = True elif opt == '--verbose': verbosity = int(val) elif opt == '--filter': @@ -6086,7 +6204,7 @@ def ParseArguments(args): try: _valid_extensions = set(val.split(',')) except ValueError: - PrintUsage('Extensions must be comma seperated list.') + PrintUsage('Extensions must be comma separated list.') elif opt == '--headers': ProcessHppHeadersOption(val) @@ -6094,6 +6212,7 @@ def ParseArguments(args): PrintUsage('No files were specified.') _SetOutputFormat(output_format) + _SetQuiet(quiet) _SetVerboseLevel(verbosity) _SetFilters(filters) _SetCountingStyle(counting_style) @@ -6114,7 +6233,9 @@ def main(): _cpplint_state.ResetErrorCounts() for filename in filenames: ProcessFile(filename, _cpplint_state.verbose_level) - _cpplint_state.PrintErrorCounts() + # If --quiet is passed, suppress printing error count unless there are errors. + if not _cpplint_state.quiet or _cpplint_state.error_count > 0: + _cpplint_state.PrintErrorCounts() sys.exit(_cpplint_state.error_count > 0) diff --git a/extras/cpplint.txt b/extras/cpplint.txt deleted file mode 100644 index db9a610a..00000000 --- a/extras/cpplint.txt +++ /dev/null @@ -1,7 +0,0 @@ -Ignoring ../src/DigitalIO/readme.txt; not a valid file name (cc, h, cpp, cu, cuh) -Ignoring ../src/SdCard/CPPLINT.cfg; not a valid file name (cc, h, cpp, cu, cuh) -Ignoring "../src/SdCard/SdioTeensy.h": file excluded by "C:\Users\bill\Documents\ArduinoSdFat\libraries\SdFat\src\SdCard\CPPLINT.cfg". File path component "SdioTeensy.h" matches pattern "SdioTeensy.h" -Ignoring ../src/common/CPPLINT.cfg; not a valid file name (cc, h, cpp, cu, cuh) -Ignoring "../src/common/PrintBasic.cpp": file excluded by "C:\Users\bill\Documents\ArduinoSdFat\libraries\SdFat\src\common\CPPLINT.cfg". File path component "PrintBasic.cpp" matches pattern "PrintBasic.cpp" -Ignoring "../src/common/PrintBasic.h": file excluded by "C:\Users\bill\Documents\ArduinoSdFat\libraries\SdFat\src\common\CPPLINT.cfg". File path component "PrintBasic.h" matches pattern "PrintBasic.h" -Ignoring "../src/common/PrintTemplates.h": file excluded by "C:\Users\bill\Documents\ArduinoSdFat\libraries\SdFat\src\common\CPPLINT.cfg". File path component "PrintTemplates.h" matches pattern "PrintTemplates.h" diff --git a/library.properties b/library.properties index e5fd70cb..11374c6a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SdFat -version=2.0.1 +version=2.0.2 license=MIT author=Bill Greiman maintainer=Bill Greiman diff --git a/src/DigitalIO/SoftSPI.h b/src/DigitalIO/SoftSPI.h index d6a13ca1..6dd58dff 100644 --- a/src/DigitalIO/SoftSPI.h +++ b/src/DigitalIO/SoftSPI.h @@ -18,7 +18,7 @@ * . */ /** - * @file + * @file * @brief Software SPI. * * @defgroup softSPI Software SPI diff --git a/src/ExFatLib/ExFatDbg.cpp b/src/ExFatLib/ExFatDbg.cpp index 39c697e3..73f602a5 100644 --- a/src/ExFatLib/ExFatDbg.cpp +++ b/src/ExFatLib/ExFatDbg.cpp @@ -25,31 +25,118 @@ #include "ExFatVolume.h" #include "upcase.h" #include "ExFatFile.h" -#include "../common/FsDateTime.h" #ifndef DOXYGEN_SHOULD_SKIP_THIS //------------------------------------------------------------------------------ -static void printHex64(print_t* pr, uint64_t n) { - char buf[17]; - char *str = &buf[sizeof(buf) - 1]; - *str = '\0'; - do { - uint8_t h = n & 15; - *--str = h < 10 ? h + '0' : h + 'A' - 10; - n >>= 4; - } while (n); - pr->println(str); +static void printHex(print_t* pr, uint8_t h); +static void printHex(print_t* pr, uint16_t val); +static void printHex(print_t* pr, uint32_t val); +static void printHex64(print_t* pr, uint64_t n); +static void println64(print_t* pr, uint64_t n); +//------------------------------------------------------------------------------ +static void dmpDirData(print_t* pr, DirGeneric_t* dir) { + for (uint8_t k = 0; k < 31; k++) { + if (k) { + pr->write(' '); + } + printHex(pr, dir->data[k]); + } + pr->println(); } //------------------------------------------------------------------------------ -static void println64(print_t* pr, uint64_t n) { - char buf[21]; - char *str = &buf[sizeof(buf) - 1]; - *str = '\0'; - do { - uint64_t m = n; - n /= 10; - *--str = m - 10*n + '0'; - } while (n); - pr->println(str); +static uint16_t exFatDirChecksum(const void* dir, uint16_t checksum) { + const uint8_t* data = reinterpret_cast(dir); + bool skip = data[0] == EXFAT_TYPE_FILE; + for (size_t i = 0; i < 32; i += (i == 1 && skip ? 3 : 1)) { + checksum = ((checksum << 15) | (checksum >> 1)) + data[i]; + } + return checksum; +} +//------------------------------------------------------------------------------ +static void printDateTime(print_t* pr, + uint32_t timeDate, uint8_t ms, int8_t tz) { + fsPrintDateTime(pr, timeDate, ms, tz); + pr->println(); +} +//------------------------------------------------------------------------------ +static void printDirBitmap(print_t* pr, DirBitmap_t* dir) { + pr->print(F("dirBitmap: 0x")); + pr->println(dir->type, HEX); + pr->print(F("flags: 0x")); + pr->println(dir->flags, HEX); + pr->print(F("firstCluster: ")); + pr->println(getLe32(dir->firstCluster)); + pr->print(F("size: ")); + println64(pr, getLe64(dir->size)); +} +//------------------------------------------------------------------------------ +static void printDirFile(print_t* pr, DirFile_t* dir) { + pr->print(F("dirFile: 0x")); + pr->println(dir->type, HEX); + pr->print(F("setCount: ")); + pr->println(dir->setCount); + pr->print(F("setChecksum: 0x")); + pr->println(getLe16(dir->setChecksum), HEX); + pr->print(F("attributes: 0x")); + pr->println(getLe16(dir->attributes), HEX); + pr->print(F("createTime: ")); + printDateTime(pr, getLe32(dir->createTime), + dir->createTimeMs, dir->createTimezone); + pr->print(F("modifyTime: ")); + printDateTime(pr, getLe32(dir->modifyTime), + dir->modifyTimeMs, dir->modifyTimezone); + pr->print(F("accessTime: ")); + printDateTime(pr, getLe32(dir->accessTime), 0, dir->accessTimezone); +} +//------------------------------------------------------------------------------ +static void printDirLabel(print_t* pr, DirLabel_t* dir) { + pr->print(F("dirLabel: 0x")); + pr->println(dir->type, HEX); + pr->print(F("labelLength: ")); + pr->println(dir->labelLength); + pr->print(F("unicode: ")); + for (size_t i = 0; i < dir->labelLength; i++) { + pr->write(dir->unicode[2*i]); + } + pr->println(); +} +//------------------------------------------------------------------------------ +static void printDirName(print_t* pr, DirName_t* dir) { + pr->print(F("dirName: 0x")); + pr->println(dir->type, HEX); + pr->print(F("unicode: ")); + for (size_t i = 0; i < 30; i += 2) { + if (dir->unicode[i] == 0) break; + pr->write(dir->unicode[i]); + } + pr->println(); +} +//------------------------------------------------------------------------------ +static void printDirStream(print_t* pr, DirStream_t* dir) { + pr->print(F("dirStream: 0x")); + pr->println(dir->type, HEX); + pr->print(F("flags: 0x")); + pr->println(dir->flags, HEX); + pr->print(F("nameLength: ")); + pr->println(dir->nameLength); + pr->print(F("nameHash: 0x")); + pr->println(getLe16(dir->nameHash), HEX); + pr->print(F("validLength: ")); + println64(pr, getLe64(dir->validLength)); + pr->print(F("firstCluster: ")); + pr->println(getLe32(dir->firstCluster)); + pr->print(F("dataLength: ")); + println64(pr, getLe64(dir->dataLength)); +} +//------------------------------------------------------------------------------ +static void printDirUpcase(print_t* pr, DirUpcase_t* dir) { + pr->print(F("dirUpcase: 0x")); + pr->println(dir->type, HEX); + pr->print(F("checksum: 0x")); + pr->println(getLe32(dir->checksum), HEX); + pr->print(F("firstCluster: ")); + pr->println(getLe32(dir->firstCluster)); + pr->print(F("size: ")); + println64(pr, getLe64(dir->size)); } //------------------------------------------------------------------------------ static void printExFatBoot(print_t* pr, pbs_t* pbs) { @@ -104,28 +191,6 @@ static void printHex(print_t* pr, uint8_t h) { pr->print(h, HEX); } //------------------------------------------------------------------------------ -static void printMbr(print_t* pr, MbrSector_t* mbr) { - pr->print(F("mbrSig: 0x")); - pr->println(getLe16(mbr->signature), HEX); - for (int i = 0; i < 4; i++) { - printHex(pr, mbr->part[i].boot); - pr->write(' '); - for (int k = 0; k < 3; k++) { - printHex(pr, mbr->part[i].beginCHS[k]); - pr->write(' '); - } - printHex(pr, mbr->part[i].type); - pr->write(' '); - for (int k = 0; k < 3; k++) { - printHex(pr, mbr->part[i].endCHS[k]); - pr->write(' '); - } - pr->print(getLe32(mbr->part[i].relativeSectors), HEX); - pr->print(' '); - pr->println(getLe32(mbr->part[i].totalSectors), HEX); - } -} -//------------------------------------------------------------------------------ static void printHex(print_t* pr, uint16_t val) { bool space = true; for (uint8_t i = 0; i < 4; i++) { @@ -156,210 +221,52 @@ static void printHex(print_t* pr, uint32_t val) { } } //------------------------------------------------------------------------------ -void ExFatPartition::dmpCluster(print_t* pr, uint32_t cluster, - uint32_t offset, uint32_t count) { - uint32_t sector = clusterStartSector(cluster) + offset; - for (uint32_t i = 0; i < count; i++) { - pr->print(F("\nSector: ")); - pr->println(sector + i, HEX); - dmpSector(pr, sector + i); - } -} -//------------------------------------------------------------------------------ -void ExFatPartition::dmpSector(print_t* pr, uint32_t sector) { - uint8_t* cache = dataCacheGet(sector, FsCache::CACHE_FOR_READ); - if (!cache) { - pr->println(F("dmpSector failed")); - return; - } - for (uint16_t i = 0; i < 512; i++) { - if (i%32 == 0) { - if (i) { - pr->println(); - } - printHex(pr, i); - } - pr->write(' '); - printHex(pr, cache[i]); - } - pr->println(); -} -//------------------------------------------------------------------------------ -void ExFatPartition::dmpBitmap(print_t* pr) { - pr->println(F("bitmap:")); - dmpSector(pr, m_clusterHeapStartSector); +static void printHex64(print_t* pr, uint64_t n) { + char buf[17]; + char *str = &buf[sizeof(buf) - 1]; + *str = '\0'; + do { + uint8_t h = n & 15; + *--str = h < 10 ? h + '0' : h + 'A' - 10; + n >>= 4; + } while (n); + pr->println(str); } //------------------------------------------------------------------------------ -static void dmpDirData(print_t* pr, DirGeneric_t* dir) { - for (uint8_t k = 0; k < 31; k++) { - if (k) { - pr->write(' '); - } - printHex(pr, dir->data[k]); - } - pr->println(); +static void println64(print_t* pr, uint64_t n) { + char buf[21]; + char *str = &buf[sizeof(buf) - 1]; + *str = '\0'; + do { + uint64_t m = n; + n /= 10; + *--str = m - 10*n + '0'; + } while (n); + pr->println(str); } //------------------------------------------------------------------------------ -void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) { - uint32_t sector = m_fatStartSector + start; - uint32_t cluster = 128*start; - pr->println(F("FAT:")); - for (uint32_t i = 0; i < count; i++) { - uint8_t* cache = dataCacheGet(sector + i, FsCache::CACHE_FOR_READ); - if (!cache) { - pr->println(F("cache read failed")); - return; - } - uint32_t* fat = reinterpret_cast(cache); - for (size_t k = 0; k < 128; k++) { - if (0 == cluster%8) { - if (k) { - pr->println(); - } - printHex(pr, cluster); - } - cluster++; +static void printMbr(print_t* pr, MbrSector_t* mbr) { + pr->print(F("mbrSig: 0x")); + pr->println(getLe16(mbr->signature), HEX); + for (int i = 0; i < 4; i++) { + printHex(pr, mbr->part[i].boot); + pr->write(' '); + for (int k = 0; k < 3; k++) { + printHex(pr, mbr->part[i].beginCHS[k]); pr->write(' '); - printHex(pr, fat[k]); } - pr->println(); - } -} -//------------------------------------------------------------------------------ -void ExFatPartition::printFat(print_t* pr) { - uint32_t next; - int8_t status; - pr->println(F("FAT:")); - for (uint32_t cluster = 0; cluster < 16; cluster++) { - status = fatGet(cluster, &next); - pr->print(cluster, HEX); + printHex(pr, mbr->part[i].type); pr->write(' '); - if (status == 0) { - next = EXFAT_EOC; + for (int k = 0; k < 3; k++) { + printHex(pr, mbr->part[i].endCHS[k]); + pr->write(' '); } - pr->println(next, HEX); - } -} -//------------------------------------------------------------------------------ -bool ExFatPartition::printVolInfo(print_t* pr) { - uint8_t* cache = dataCacheGet(0, FsCache::CACHE_FOR_READ); - if (!cache) { - pr->println(F("read mbr failed")); - return false; - } - MbrSector_t* mbr = reinterpret_cast(cache); - printMbr(pr, mbr); - uint32_t volStart = getLe32(mbr->part->relativeSectors); - uint32_t volSize = getLe32(mbr->part->totalSectors); - if (volSize == 0) { - pr->print(F("bad partition size")); - return false; - } - cache = dataCacheGet(volStart, FsCache::CACHE_FOR_READ); - if (!cache) { - pr->println(F("read pbs failed")); - return false; - } - printExFatBoot(pr, reinterpret_cast(cache)); - return true; -} -//------------------------------------------------------------------------------ -static void printDateTime(print_t* pr, - uint32_t timeDate, uint8_t ms, int8_t tz) { - fsPrintDateTime(pr, timeDate, ms, tz); - pr->println(); -} -//------------------------------------------------------------------------------ -static void printDirBitmap(print_t* pr, DirBitmap_t* dir) { - pr->print(F("dirBitmap: 0x")); - pr->println(dir->type, HEX); - pr->print(F("flags: 0x")); - pr->println(dir->flags, HEX); - pr->print(F("firstCluster: ")); - pr->println(getLe32(dir->firstCluster)); - pr->print(F("size: ")); - println64(pr, getLe64(dir->size)); -} -//------------------------------------------------------------------------------ -static void printDirUpcase(print_t* pr, DirUpcase_t* dir) { - pr->print(F("dirUpcase: 0x")); - pr->println(dir->type, HEX); - pr->print(F("checksum: 0x")); - pr->println(getLe32(dir->checksum), HEX); - pr->print(F("firstCluster: ")); - pr->println(getLe32(dir->firstCluster)); - pr->print(F("size: ")); - println64(pr, getLe64(dir->size)); -} -//------------------------------------------------------------------------------ -static void printDirLabel(print_t* pr, DirLabel_t* dir) { - pr->print(F("dirLabel: 0x")); - pr->println(dir->type, HEX); - pr->print(F("labelLength: ")); - pr->println(dir->labelLength); - pr->print(F("unicode: ")); - for (size_t i = 0; i < dir->labelLength; i++) { - pr->write(dir->unicode[2*i]); - } - pr->println(); -} -//------------------------------------------------------------------------------ -static void printDirFile(print_t* pr, DirFile_t* dir) { - pr->print(F("dirFile: 0x")); - pr->println(dir->type, HEX); - pr->print(F("setCount: ")); - pr->println(dir->setCount); - pr->print(F("setChecksum: 0x")); - pr->println(getLe16(dir->setChecksum), HEX); - pr->print(F("attributes: 0x")); - pr->println(getLe16(dir->attributes), HEX); - pr->print(F("createTime: ")); - printDateTime(pr, getLe32(dir->createTime), - dir->createTimeMs, dir->createTimezone); - pr->print(F("modifyTime: ")); - printDateTime(pr, getLe32(dir->modifyTime), - dir->modifyTimeMs, dir->modifyTimezone); - pr->print(F("accessTime: ")); - printDateTime(pr, getLe32(dir->accessTime), 0, dir->accessTimezone); -} -//------------------------------------------------------------------------------ -static void printDirStream(print_t* pr, DirStream_t* dir) { - pr->print(F("dirStream: 0x")); - pr->println(dir->type, HEX); - pr->print(F("flags: 0x")); - pr->println(dir->flags, HEX); - pr->print(F("nameLength: ")); - pr->println(dir->nameLength); - pr->print(F("nameHash: 0x")); - pr->println(getLe16(dir->nameHash), HEX); - pr->print(F("validLength: ")); - println64(pr, getLe64(dir->validLength)); - pr->print(F("firstCluster: ")); - pr->println(getLe32(dir->firstCluster)); - pr->print(F("dataLength: ")); - println64(pr, getLe64(dir->dataLength)); -} -//------------------------------------------------------------------------------ -static void printDirName(print_t* pr, DirName_t* dir) { - pr->print(F("dirName: 0x")); - pr->println(dir->type, HEX); - pr->print(F("unicode: ")); - for (size_t i = 0; i < 30; i += 2) { - if (dir->unicode[i] == 0) break; - pr->write(dir->unicode[i]); - } - pr->println(); -} -//------------------------------------------------------------------------------ -static uint16_t exFatDirChecksum(const void* dir, uint16_t checksum) { - const uint8_t* data = reinterpret_cast(dir); - bool skip = data[0] == EXFAT_TYPE_FILE; - for (size_t i = 0; i < 32; i += (i == 1 && skip ? 3 : 1)) { - checksum = ((checksum << 15) | (checksum >> 1)) + data[i]; + pr->print(getLe32(mbr->part[i].relativeSectors), HEX); + pr->print(' '); + pr->println(getLe32(mbr->part[i].totalSectors), HEX); } - return checksum; } -//------------------------------------------------------------------------------ +//============================================================================== void ExFatPartition::checkUpcase(print_t* pr) { bool skip = false; uint16_t u = 0; @@ -430,6 +337,66 @@ void ExFatPartition::checkUpcase(print_t* pr) { pr->println(F("Done checkUpcase")); } //------------------------------------------------------------------------------ +void ExFatPartition::dmpBitmap(print_t* pr) { + pr->println(F("bitmap:")); + dmpSector(pr, m_clusterHeapStartSector); +} +//------------------------------------------------------------------------------ +void ExFatPartition::dmpCluster(print_t* pr, uint32_t cluster, + uint32_t offset, uint32_t count) { + uint32_t sector = clusterStartSector(cluster) + offset; + for (uint32_t i = 0; i < count; i++) { + pr->print(F("\nSector: ")); + pr->println(sector + i, HEX); + dmpSector(pr, sector + i); + } +} +//------------------------------------------------------------------------------ +void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) { + uint32_t sector = m_fatStartSector + start; + uint32_t cluster = 128*start; + pr->println(F("FAT:")); + for (uint32_t i = 0; i < count; i++) { + uint8_t* cache = dataCacheGet(sector + i, FsCache::CACHE_FOR_READ); + if (!cache) { + pr->println(F("cache read failed")); + return; + } + uint32_t* fat = reinterpret_cast(cache); + for (size_t k = 0; k < 128; k++) { + if (0 == cluster%8) { + if (k) { + pr->println(); + } + printHex(pr, cluster); + } + cluster++; + pr->write(' '); + printHex(pr, fat[k]); + } + pr->println(); + } +} +//------------------------------------------------------------------------------ +void ExFatPartition::dmpSector(print_t* pr, uint32_t sector) { + uint8_t* cache = dataCacheGet(sector, FsCache::CACHE_FOR_READ); + if (!cache) { + pr->println(F("dmpSector failed")); + return; + } + for (uint16_t i = 0; i < 512; i++) { + if (i%32 == 0) { + if (i) { + pr->println(); + } + printHex(pr, i); + } + pr->write(' '); + printHex(pr, cache[i]); + } + pr->println(); +} +//------------------------------------------------------------------------------ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) { DirGeneric_t* dir = nullptr; DirFile_t* dirFile; @@ -547,6 +514,21 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) { return true; } //------------------------------------------------------------------------------ +void ExFatPartition::printFat(print_t* pr) { + uint32_t next; + int8_t status; + pr->println(F("FAT:")); + for (uint32_t cluster = 0; cluster < 16; cluster++) { + status = fatGet(cluster, &next); + pr->print(cluster, HEX); + pr->write(' '); + if (status == 0) { + next = EXFAT_EOC; + } + pr->println(next, HEX); + } +} +//------------------------------------------------------------------------------ void ExFatPartition::printUpcase(print_t* pr) { uint8_t* upcase = nullptr; uint32_t sector; @@ -593,5 +575,27 @@ void ExFatPartition::printUpcase(print_t* pr) { printHex(pr, checksum); pr->println(); } +//------------------------------------------------------------------------------ +bool ExFatPartition::printVolInfo(print_t* pr) { + uint8_t* cache = dataCacheGet(0, FsCache::CACHE_FOR_READ); + if (!cache) { + pr->println(F("read mbr failed")); + return false; + } + MbrSector_t* mbr = reinterpret_cast(cache); + printMbr(pr, mbr); + uint32_t volStart = getLe32(mbr->part->relativeSectors); + uint32_t volSize = getLe32(mbr->part->totalSectors); + if (volSize == 0) { + pr->print(F("bad partition size")); + return false; + } + cache = dataCacheGet(volStart, FsCache::CACHE_FOR_READ); + if (!cache) { + pr->println(F("read pbs failed")); + return false; + } + printExFatBoot(pr, reinterpret_cast(cache)); + return true; +} #endif // DOXYGEN_SHOULD_SKIP_THIS - diff --git a/src/ExFatLib/ExFatFile.cpp b/src/ExFatLib/ExFatFile.cpp index be28814a..b7dede25 100644 --- a/src/ExFatLib/ExFatFile.cpp +++ b/src/ExFatLib/ExFatFile.cpp @@ -27,7 +27,7 @@ #include "ExFatFile.h" #include "ExFatVolume.h" #include "upcase.h" -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::close() { bool rtn = sync(); m_attributes = FILE_ATTR_CLOSED; @@ -35,6 +35,20 @@ bool ExFatFile::close() { return rtn; } //------------------------------------------------------------------------------ +bool ExFatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) { + if (!isContiguous()) { + return false; + } + if (bgnSector) { + *bgnSector = firstSector(); + } + if (endSector) { + *endSector = firstSector() + + ((m_validLength - 1) >> m_vol->bytesPerSectorShift()); + } + return true; +} +//------------------------------------------------------------------------------ void ExFatFile::fgetpos(fspos_t* pos) { pos->position = m_curPosition; pos->cluster = m_curCluster; @@ -68,12 +82,61 @@ int ExFatFile::fgets(char* str, int num, char* delim) { return n; } //------------------------------------------------------------------------------ +uint32_t ExFatFile::firstSector() { + return m_firstCluster ? m_vol->clusterStartSector(m_firstCluster) : 0; +} +//------------------------------------------------------------------------------ void ExFatFile::fsetpos(const fspos_t* pos) { m_curPosition = pos->position; m_curCluster = pos->cluster; } -//----------------------------------------------------------------------------- -size_t ExFatFile::getName(ExChar_t *name, size_t length) { +//------------------------------------------------------------------------------ +bool ExFatFile::getAccessDateTime(uint16_t* pdate, uint16_t* ptime) { + DirFile_t* df = reinterpret_cast + (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ)); + if (!df) { + DBG_FAIL_MACRO; + goto fail; + } + *pdate = getLe16(df->accessDate); + *ptime = getLe16(df->accessTime); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +bool ExFatFile::getCreateDateTime(uint16_t* pdate, uint16_t* ptime) { + DirFile_t* df = reinterpret_cast + (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ)); + if (!df) { + DBG_FAIL_MACRO; + goto fail; + } + *pdate = getLe16(df->createDate); + *ptime = getLe16(df->createTime); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +bool ExFatFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) { + DirFile_t* df = reinterpret_cast + (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ)); + if (!df) { + DBG_FAIL_MACRO; + goto fail; + } + *pdate = getLe16(df->modifyDate); + *ptime = getLe16(df->modifyTime); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +size_t ExFatFile::getName(ExChar_t* name, size_t length) { DirName_t* dn; DirPos_t pos = m_dirPos; size_t n = 0; @@ -108,11 +171,11 @@ size_t ExFatFile::getName(ExChar_t *name, size_t length) { *name = 0; return 0; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::open(const ExChar_t* path, int oflag) { return open(ExFatVolume::cwv(), path, oflag); } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::open(ExFatVolume* vol, const ExChar_t* path, int oflag) { return vol && open(vol->vwd(), path, oflag); } @@ -156,7 +219,7 @@ bool ExFatFile::open(ExFatFile* dirFile, const ExChar_t* path, oflag_t oflag) { } return open(dirFile, &fname, oflag); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -170,7 +233,7 @@ bool ExFatFile::open(ExFatFile* dirFile, uint32_t index, oflag_t oflag) { } return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::openNext(ExFatFile* dir, oflag_t oflag) { if (isOpen() || !dir->isDir() || (dir->curPosition() & 0X1F)) { DBG_FAIL_MACRO; @@ -400,13 +463,23 @@ bool ExFatFile::openRootFile(ExFatFile* dir, const ExChar_t* name, dirFile->type = EXFAT_TYPE_FILE; m_setCount = freeNeed - 1; dirFile->setCount = m_setCount; + if (FsDateTime::callback) { uint16_t date, time; uint8_t ms10; FsDateTime::callback(&date, &time, &ms10); - dirFile->createTimeMs = ms10; - setLe16(dirFile->createTime, time); setLe16(dirFile->createDate, date); + setLe16(dirFile->createTime, time); + dirFile->createTimeMs = ms10; + } else { + setLe16(dirFile->createDate, FS_DEFAULT_DATE); + setLe16(dirFile->modifyDate, FS_DEFAULT_DATE); + setLe16(dirFile->accessDate, FS_DEFAULT_DATE); + if (FS_DEFAULT_TIME) { + setLe16(dirFile->createTime, FS_DEFAULT_TIME); + setLe16(dirFile->modifyTime, FS_DEFAULT_TIME); + setLe16(dirFile->accessTime, FS_DEFAULT_TIME); + } } } else if (i == 1) { dirStream = reinterpret_cast(cache); @@ -438,7 +511,7 @@ bool ExFatFile::openRootFile(ExFatFile* dir, const ExChar_t* name, m_flags = 0; return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::openRoot(ExFatVolume* vol) { if (isOpen()) { DBG_FAIL_MACRO; @@ -494,7 +567,7 @@ bool ExFatFile::parsePathName(const ExChar_t* path, fname->len = len; return true; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ int ExFatFile::peek() { uint64_t curPosition = m_curPosition; uint32_t curCluster = m_curCluster; @@ -503,44 +576,7 @@ int ExFatFile::peek() { m_curCluster = curCluster; return c; } -//----------------------------------------------------------------------------- -size_t ExFatFile::printName(print_t* pr) { - DirName_t* dn; - DirPos_t pos = m_dirPos; - size_t n = 0; - uint8_t in; - uint8_t buf[15]; - if (!isOpen()) { - DBG_FAIL_MACRO; - goto fail; - } - for (uint8_t is = 1; is < m_setCount; is++) { - if (m_vol->dirSeek(&pos, is == 1 ? 64: 32) != 1) { - DBG_FAIL_MACRO; - goto fail; - } - dn = reinterpret_cast - (m_vol->dirCache(&pos, FsCache::CACHE_FOR_READ)); - if (!dn || dn->type != EXFAT_TYPE_NAME) { - DBG_FAIL_MACRO; - goto fail; - } - for (in = 0; in < 15; in++) { - uint16_t c = getLe16(dn->unicode + 2*in); - if (!c) { - break;; - } - buf[in] = c < 0X7f ? c : '?'; - n++; - } - pr->write(buf, in); - } - return n; - - fail: - return 0; -} -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ int ExFatFile::read(void* buf, size_t count) { uint8_t* dst = reinterpret_cast(buf); int8_t fg; @@ -604,7 +640,7 @@ int ExFatFile::read(void* buf, size_t count) { #if USE_MULTI_SECTOR_IO } else if (toRead >= 2*m_vol->bytesPerSector()) { uint32_t ns = toRead >> m_vol->bytesPerSectorShift(); - // Limit writes to current cluster. + // Limit reads to current cluster. uint32_t maxNs = m_vol->sectorsPerCluster() - (clusterOffset >> m_vol->bytesPerSectorShift()); if (ns > maxNs) { @@ -639,7 +675,7 @@ int ExFatFile::read(void* buf, size_t count) { } return count - toRead; -fail: + fail: m_error |= READ_ERROR; return -1; } @@ -652,7 +688,7 @@ bool ExFatFile::remove(const ExChar_t* path) { } return file.remove(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -702,11 +738,11 @@ bool ExFatFile::seekSet(uint64_t pos) { } } -done: + done: m_curPosition = pos; return true; -fail: + fail: m_curCluster = tmp; return false; } diff --git a/src/ExFatLib/ExFatFile.h b/src/ExFatLib/ExFatFile.h index 55ead74e..7e7241e1 100644 --- a/src/ExFatLib/ExFatFile.h +++ b/src/ExFatLib/ExFatFile.h @@ -118,7 +118,7 @@ class ExFatFile { /** \return The number of bytes available from the current position * to EOF for normal files. INT_MAX is returned for very large files. * - * available64() is recomended for very large files. + * available64() is recommended for very large files. * * Zero is returned for directory files. * @@ -133,6 +133,16 @@ class ExFatFile { * \return true for success or false for failure. */ bool close(); + /** Check for contiguous file and return its raw sector range. + * + * \param[out] bgnSector the first sector address for the file. + * \param[out] endSector the last sector address for the file. + * + * Parameters may be nullptr. + * + * \return true for success or false for failure. + */ + bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector); /** \return The current position for a file or directory. */ uint64_t curPosition() const {return m_curPosition;} @@ -163,8 +173,8 @@ class ExFatFile { * Get a string from a file. * * fgets() reads bytes from a file into the array pointed to by \a str, until - * \a num - 1 bytes are read, or a delimiter is read and transferred to \a str, - * or end-of-file is encountered. The string is then terminated + * \a num - 1 bytes are read, or a delimiter is read and transferred to + * \a str, or end-of-file is encountered. The string is then terminated * with a null byte. * * fgets() deletes CR, '\\r', from the string. This insures only a '\\n' @@ -177,12 +187,15 @@ class ExFatFile { * \param[in] delim Optional set of delimiters. The default is "\n". * * \return For success fgets() returns the length of the string in \a str. - * If no data is read, fgets() returns zero for EOF or -1 if an error occurred. + * If no data is read, fgets() returns zero for EOF or -1 if an error + * occurred. */ int fgets(char* str, int num, char* delim = nullptr); /** \return The total number of bytes in a file. */ uint64_t fileSize() {return m_validLength;} - /** set position for streams + /** \return Address of first sector or zero for empty file. */ + uint32_t firstSector(); + /** Set position for streams * \param[in] pos struct with value for new position */ void fsetpos(const fspos_t* pos); @@ -195,19 +208,43 @@ class ExFatFile { * \param[in] size The size of the array in characters. * \return the name length. */ - size_t getName(ExChar_t *name, size_t size); + size_t getName(ExChar_t* name, size_t size); /** Clear all error bits. */ void clearError() { m_error = 0; } - /** Set writeError to zero */ + /** Clear writeError. */ void clearWriteError() { m_error &= ~WRITE_ERROR; } + /** Get a file's access date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getAccessDateTime(uint16_t* pdate, uint16_t* ptime); + /** Get a file's create date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime); /** \return All error bits. */ uint8_t getError() { return isOpen() ? m_error : 0XFF; } + /** Get a file's modify date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime); /** \return value of writeError */ bool getWriteError() { return isOpen() ? m_error & WRITE_ERROR : true; @@ -297,10 +334,12 @@ class ExFatFile { * O_CREAT - If the file exists, this flag has no effect except as noted * under O_EXCL below. Otherwise, the file shall be created * - * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. + * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file + * exists. * * O_TRUNC - If the file exists and is a regular file, and the file is - * successfully opened and is not read only, its length shall be truncated to 0. + * successfully opened and is not read only, its length shall be truncated + * to 0. * * WARNING: A given file must not be opened by more than one file object * or file corruption may occur. @@ -586,10 +625,10 @@ class ExFatFile { */ /** Set a file's timestamps in its directory entry. * - * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive - * OR of flags from the following list + * \param[in] flags Values for \a flags are constructed by a + * bitwise-inclusive OR of flags from the following list * - * T_ACCESS - Set the file's last access date. + * T_ACCESS - Set the file's last access date and time. * * T_CREATE - Set the file's creation date and time. * diff --git a/src/ExFatLib/ExFatFilePrint.cpp b/src/ExFatLib/ExFatFilePrint.cpp index 4b4e5827..5b10df49 100644 --- a/src/ExFatLib/ExFatFilePrint.cpp +++ b/src/ExFatLib/ExFatFilePrint.cpp @@ -27,59 +27,6 @@ #include "ExFatFile.h" #include "upcase.h" #include "ExFatVolume.h" -//----------------------------------------------------------------------------- -size_t ExFatFile::printFileSize(print_t* pr) { - uint64_t n = m_validLength; - char buf[21]; - char *str = &buf[sizeof(buf) - 1]; - char *bgn = str - 12; - *str = '\0'; - do { - uint64_t m = n; - n /= 10; - *--str = m - 10*n + '0'; - } while (n); - while (str > bgn) { - *--str = ' '; - } - return pr->write(str); -} -//----------------------------------------------------------------------------- -size_t ExFatFile::printAccessDateTime(print_t* pr) { - DirFile_t* df = reinterpret_cast - (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ)); - if (!df) { - DBG_FAIL_MACRO; - goto fail; - } - return fsPrintDateTime(pr, getLe32(df->accessTime)); -fail: - return 0; -} -//----------------------------------------------------------------------------- -size_t ExFatFile::printCreateDateTime(print_t* pr) { - DirFile_t* df = reinterpret_cast - (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ)); - if (!df) { - DBG_FAIL_MACRO; - goto fail; - } - return fsPrintDateTime(pr, getLe32(df->createTime)); -fail: - return 0; -} -//----------------------------------------------------------------------------- -size_t ExFatFile::printModifyDateTime(print_t* pr) { - DirFile_t* df = reinterpret_cast - (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ)); - if (!df) { - DBG_FAIL_MACRO; - goto fail; - } - return fsPrintDateTime(pr, getLe32(df->modifyTime)); -fail: - return 0; -} //------------------------------------------------------------------------------ bool ExFatFile::ls(print_t* pr) { ExFatFile file; @@ -151,6 +98,84 @@ bool ExFatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) { fail: return false; } +//------------------------------------------------------------------------------ +size_t ExFatFile::printAccessDateTime(print_t* pr) { + uint16_t date; + uint16_t time; + if (getAccessDateTime(&date, &time)) { + return fsPrintDateTime(pr, date, time); + } + return 0; +} +//------------------------------------------------------------------------------ +size_t ExFatFile::printCreateDateTime(print_t* pr) { + uint16_t date; + uint16_t time; + if (getCreateDateTime(&date, &time)) { + return fsPrintDateTime(pr, date, time); + } + return 0; +} +//------------------------------------------------------------------------------ +size_t ExFatFile::printFileSize(print_t* pr) { + uint64_t n = m_validLength; + char buf[21]; + char *str = &buf[sizeof(buf) - 1]; + char *bgn = str - 12; + *str = '\0'; + do { + uint64_t m = n; + n /= 10; + *--str = m - 10*n + '0'; + } while (n); + while (str > bgn) { + *--str = ' '; + } + return pr->write(str); +} +//------------------------------------------------------------------------------ +size_t ExFatFile::printModifyDateTime(print_t* pr) { + uint16_t date; + uint16_t time; + if (getModifyDateTime(&date, &time)) { + return fsPrintDateTime(pr, date, time); + } + return 0; +} +//------------------------------------------------------------------------------ +size_t ExFatFile::printName(print_t* pr) { + DirName_t* dn; + DirPos_t pos = m_dirPos; + size_t n = 0; + uint8_t in; + uint8_t buf[15]; + if (!isOpen()) { + DBG_FAIL_MACRO; + goto fail; + } + for (uint8_t is = 1; is < m_setCount; is++) { + if (m_vol->dirSeek(&pos, is == 1 ? 64: 32) != 1) { + DBG_FAIL_MACRO; + goto fail; + } + dn = reinterpret_cast + (m_vol->dirCache(&pos, FsCache::CACHE_FOR_READ)); + if (!dn || dn->type != EXFAT_TYPE_NAME) { + DBG_FAIL_MACRO; + goto fail; + } + for (in = 0; in < 15; in++) { + uint16_t c = getLe16(dn->unicode + 2*in); + if (!c) { + break;; + } + buf[in] = c < 0X7f ? c : '?'; + n++; + } + pr->write(buf, in); + } + return n; - - + fail: + return 0; +} diff --git a/src/ExFatLib/ExFatFileWrite.cpp b/src/ExFatLib/ExFatFileWrite.cpp index 5680ebc9..bdf84125 100644 --- a/src/ExFatLib/ExFatFileWrite.cpp +++ b/src/ExFatLib/ExFatFileWrite.cpp @@ -27,11 +27,8 @@ #include "ExFatFile.h" #include "ExFatVolume.h" #include "upcase.h" -//============================================================================= +//============================================================================== #if READ_ONLY -bool ExFatFile::sync() { - return false; -} bool ExFatFile::mkdir(ExFatFile* parent, const ExChar_t* path, bool pFlag) { (void) parent; (void)path; @@ -51,18 +48,20 @@ bool ExFatFile::rename(ExFatFile* dirFile, const ExChar_t* newPath) { (void)newPath; return false; } +bool ExFatFile::sync() { + return false; +} bool ExFatFile::truncate() { return false; } - size_t ExFatFile::write(const void* buf, size_t nbyte) { (void)buf; (void)nbyte; return false; } -//============================================================================= +//============================================================================== #else // READ_ONLY -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ static uint16_t exFatDirChecksum(const uint8_t* data, uint16_t checksum) { bool skip = data[0] == EXFAT_TYPE_FILE; for (size_t i = 0; i < 32; i += i == 1 && skip ? 3 : 1) { @@ -70,7 +69,7 @@ static uint16_t exFatDirChecksum(const uint8_t* data, uint16_t checksum) { } return checksum; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::addCluster() { uint32_t find = m_vol->bitmapFind(m_curCluster ? m_curCluster + 1 : 0, 1); if (find < 2) { @@ -119,7 +118,7 @@ bool ExFatFile::addCluster() { fail: return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::addDirCluster() { uint32_t sector; uint32_t dl = isRoot() ? m_vol->rootLength() : m_dataLength; @@ -195,7 +194,7 @@ bool ExFatFile::mkdir(ExFatFile* parent, const ExChar_t* path, bool pFlag) { } return mkdir(parent, &fname); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -225,7 +224,7 @@ bool ExFatFile::mkdir(ExFatFile* parent, ExName_t* fname) { m_flags = FILE_FLAG_READ | FILE_FLAG_CONTIGUOUS | FILE_FLAG_DIR_DIRTY; return sync(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -342,7 +341,7 @@ bool ExFatFile::rename(ExFatFile* dirFile, const ExChar_t* newPath) { oldFile.m_attributes = FILE_ATTR_FILE; return oldFile.remove(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -375,10 +374,10 @@ bool ExFatFile::rmdir() { m_flags |= FILE_FLAG_WRITE; return remove(); -fail: + fail: return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFile::sync() { if (!isOpen()) { return true; @@ -420,7 +419,6 @@ bool ExFatFile::syncDir() { setCount = df->setCount; setLe16(df->attributes, m_attributes & FILE_ATTR_COPY); if (FsDateTime::callback) { - m_vol->dataCacheDirty(); uint16_t date, time; uint8_t ms10; FsDateTime::callback(&date, &time, &ms10); @@ -430,6 +428,7 @@ bool ExFatFile::syncDir() { setLe16(df->accessTime, time); setLe16(df->accessDate, date); } + m_vol->dataCacheDirty(); break; case EXFAT_TYPE_STREAM: @@ -460,7 +459,7 @@ bool ExFatFile::syncDir() { goto fail; } } - df = reinterpret_cast + df = reinterpret_cast (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_WRITE)); if (!df) { DBG_FAIL_MACRO; @@ -559,7 +558,7 @@ bool ExFatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, goto fail; } } - df = reinterpret_cast + df = reinterpret_cast (m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_WRITE)); if (!df) { DBG_FAIL_MACRO; @@ -778,10 +777,9 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) { m_validLength = m_curPosition; } } - if (m_curPosition > m_dataLength) { m_dataLength = m_curPosition; - // update fileSize and insure sync will update dir entr + // update fileSize and insure sync will update dir entry m_flags |= FILE_FLAG_DIR_DIRTY; } else if (FsDateTime::callback) { // insure sync will update modified date and time @@ -789,7 +787,7 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) { } return nbyte; -fail: + fail: // return for write error m_error |= WRITE_ERROR; return -1; diff --git a/src/ExFatLib/ExFatFormatter.cpp b/src/ExFatLib/ExFatFormatter.cpp index 378e61dc..c465661b 100644 --- a/src/ExFatLib/ExFatFormatter.cpp +++ b/src/ExFatLib/ExFatFormatter.cpp @@ -25,7 +25,7 @@ #define DBG_FILE "ExFatFormatter.cpp" #include "../common/DebugMacros.h" #include "ExFatFormatter.h" -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ // Formatter assumes 512 byte sectors. const uint32_t BOOT_BACKUP_OFFSET = 12; const uint16_t BYTES_PER_SECTOR = 512; @@ -35,7 +35,7 @@ const uint16_t MINIMUM_UPCASE_SKIP = 512; const uint32_t BITMAP_CLUSTER = 2; const uint32_t UPCASE_CLUSTER = 3; const uint32_t ROOT_CLUSTER = 4; -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ #define PRINT_FORMAT_PROGRESS 1 #if !PRINT_FORMAT_PROGRESS #define writeMsg(pr, str) @@ -44,7 +44,7 @@ const uint32_t ROOT_CLUSTER = 4; #else // PRINT_FORMAT_PROGRESS #define writeMsg(pr, str) if (pr) pr->write(str) #endif // PRINT_FORMAT_PROGRESS -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) { #if !PRINT_FORMAT_PROGRESS (void)pr; @@ -287,7 +287,7 @@ bool ExFatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) { writeMsg(pr, "Format failed\r\n"); return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFormatter::syncUpcase() { uint16_t index = m_upcaseSize & SECTOR_MASK; if (!index) { @@ -298,7 +298,7 @@ bool ExFatFormatter::syncUpcase() { } return m_dev->writeSector(m_upcaseSector, m_secBuf); } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFormatter::writeUpcaseByte(uint8_t b) { uint16_t index = m_upcaseSize & SECTOR_MASK; m_secBuf[index] = b; @@ -309,11 +309,11 @@ bool ExFatFormatter::writeUpcaseByte(uint8_t b) { } return true; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFormatter::writeUpcaseUnicode(uint16_t unicode) { return writeUpcaseByte(unicode) && writeUpcaseByte(unicode >> 8); } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatFormatter::writeUpcase(uint32_t sector) { uint32_t n; uint32_t ns; diff --git a/src/ExFatLib/ExFatPartition.cpp b/src/ExFatLib/ExFatPartition.cpp index fc3443ee..9c34dd34 100644 --- a/src/ExFatLib/ExFatPartition.cpp +++ b/src/ExFatLib/ExFatPartition.cpp @@ -26,12 +26,7 @@ #include "../common/DebugMacros.h" #include "ExFatVolume.h" #include "../common/FsStructs.h" -//----------------------------------------------------------------------------- -void FsCache::invalidate() { - m_status = 0; - m_sector = 0XFFFFFFFF; -} -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ uint8_t* FsCache::get(uint32_t sector, uint8_t option) { if (!m_blockDev) { DBG_FAIL_MACRO; @@ -54,10 +49,15 @@ uint8_t* FsCache::get(uint32_t sector, uint8_t option) { m_status |= option & CACHE_STATUS_MASK; return m_cacheBuffer; -fail: + fail: return nullptr; } //------------------------------------------------------------------------------ +void FsCache::invalidate() { + m_status = 0; + m_sector = 0XFFFFFFFF; +} +//------------------------------------------------------------------------------ bool FsCache::sync() { if (m_status & CACHE_STATUS_DIRTY) { if (!m_blockDev->writeSector(m_sector, m_cacheBuffer)) { @@ -68,68 +68,10 @@ bool FsCache::sync() { } return true; -fail: - return false; -} -//============================================================================= -bool ExFatPartition::init(BlockDevice* dev, uint8_t part) { - uint32_t volStart = 0; - uint8_t *cache; - pbs_t* pbs; - BpbExFat_t* bpb; - MbrSector_t* mbr; - MbrPart_t* mp; - - m_fatType = 0; - m_blockDev = dev; - cacheInit(m_blockDev); - cache = dataCacheGet(0, FsCache::CACHE_FOR_READ); - if (part > 4 || !cache) { - DBG_FAIL_MACRO; - goto fail; - } - if (part >= 1) { - mbr = reinterpret_cast(cache); - mp = &mbr->part[part - 1]; - if ((mp->boot != 0 && mp->boot != 0X80) || mp->type == 0) { - DBG_FAIL_MACRO; - goto fail; - } - volStart = getLe32(mp->relativeSectors); - cache = dataCacheGet(volStart, FsCache::CACHE_FOR_READ); - if (!cache) { - DBG_FAIL_MACRO; - goto fail; - } - } - pbs = reinterpret_cast(cache); - if (strncmp(pbs->oemName, "EXFAT", 5)) { - DBG_FAIL_MACRO; - goto fail; - } - bpb = reinterpret_cast(pbs->bpb); - if (bpb->bytesPerSectorShift != m_bytesPerSectorShift) { - DBG_FAIL_MACRO; - goto fail; - } - m_fatStartSector = volStart + getLe32(bpb->fatOffset); - m_fatLength = getLe32(bpb->fatLength); - m_clusterHeapStartSector = volStart + getLe32(bpb->clusterHeapOffset); - m_clusterCount = getLe32(bpb->clusterCount); - m_rootDirectoryCluster = getLe32(bpb->rootDirectoryCluster); - m_sectorsPerClusterShift = bpb->sectorsPerClusterShift; - m_bytesPerCluster = 1UL << (m_bytesPerSectorShift + m_sectorsPerClusterShift); - m_clusterMask = m_bytesPerCluster - 1; - // Set m_bitmapStart to first free cluster. - m_bitmapStart = 0; - bitmapFind(0, 1); - m_fatType = FAT_TYPE_EXFAT; - return true; - fail: return false; } -//----------------------------------------------------------------------------- +//============================================================================== // return 0 if error, 1 if no space, else start cluster. uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) { uint32_t start = cluster ? cluster - 2 : m_bitmapStart; @@ -178,7 +120,7 @@ uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) { } return 0; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatPartition::bitmapModify(uint32_t cluster, uint32_t count, bool value) { uint32_t sector; @@ -229,7 +171,7 @@ bool ExFatPartition::bitmapModify(uint32_t cluster, fail: return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ uint32_t ExFatPartition::chainSize(uint32_t cluster) { uint32_t n = 0; int8_t status; @@ -240,14 +182,14 @@ uint32_t ExFatPartition::chainSize(uint32_t cluster) { } while (status); return n; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ uint8_t* ExFatPartition::dirCache(DirPos_t* pos, uint8_t options) { uint32_t sector = clusterStartSector(pos->cluster); sector += (m_clusterMask & pos->position) >> m_bytesPerSectorShift; uint8_t* cache = dataCacheGet(sector, options); return cache ? cache + (pos->position & m_sectorMask) : nullptr; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ // return -1 error, 0 EOC, 1 OK int8_t ExFatPartition::dirSeek(DirPos_t* pos, uint32_t offset) { int8_t status; @@ -266,10 +208,10 @@ int8_t ExFatPartition::dirSeek(DirPos_t* pos, uint32_t offset) { } return 1; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ uint8_t ExFatPartition::fatGet(uint32_t cluster, uint32_t* value) { uint8_t* cache; -uint32_t next; + uint32_t next; uint32_t sector; if (cluster > (m_clusterCount + 1)) { @@ -290,7 +232,7 @@ uint32_t next; *value = next; return 1; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatPartition::fatPut(uint32_t cluster, uint32_t value) { uint32_t sector; uint8_t* cache; @@ -310,7 +252,7 @@ bool ExFatPartition::fatPut(uint32_t cluster, uint32_t value) { fail: return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool ExFatPartition::freeChain(uint32_t cluster) { uint32_t next; uint32_t start = cluster; @@ -340,7 +282,7 @@ bool ExFatPartition::freeChain(uint32_t cluster) { fail: return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ uint32_t ExFatPartition::freeClusterCount() { uint32_t nc = 0; uint32_t sector = m_clusterHeapStartSector; @@ -369,7 +311,65 @@ uint32_t ExFatPartition::freeClusterCount() { } } } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ +bool ExFatPartition::init(BlockDevice* dev, uint8_t part) { + uint32_t volStart = 0; + uint8_t* cache; + pbs_t* pbs; + BpbExFat_t* bpb; + MbrSector_t* mbr; + MbrPart_t* mp; + + m_fatType = 0; + m_blockDev = dev; + cacheInit(m_blockDev); + cache = dataCacheGet(0, FsCache::CACHE_FOR_READ); + if (part > 4 || !cache) { + DBG_FAIL_MACRO; + goto fail; + } + if (part >= 1) { + mbr = reinterpret_cast(cache); + mp = &mbr->part[part - 1]; + if ((mp->boot != 0 && mp->boot != 0X80) || mp->type == 0) { + DBG_FAIL_MACRO; + goto fail; + } + volStart = getLe32(mp->relativeSectors); + cache = dataCacheGet(volStart, FsCache::CACHE_FOR_READ); + if (!cache) { + DBG_FAIL_MACRO; + goto fail; + } + } + pbs = reinterpret_cast(cache); + if (strncmp(pbs->oemName, "EXFAT", 5)) { + DBG_FAIL_MACRO; + goto fail; + } + bpb = reinterpret_cast(pbs->bpb); + if (bpb->bytesPerSectorShift != m_bytesPerSectorShift) { + DBG_FAIL_MACRO; + goto fail; + } + m_fatStartSector = volStart + getLe32(bpb->fatOffset); + m_fatLength = getLe32(bpb->fatLength); + m_clusterHeapStartSector = volStart + getLe32(bpb->clusterHeapOffset); + m_clusterCount = getLe32(bpb->clusterCount); + m_rootDirectoryCluster = getLe32(bpb->rootDirectoryCluster); + m_sectorsPerClusterShift = bpb->sectorsPerClusterShift; + m_bytesPerCluster = 1UL << (m_bytesPerSectorShift + m_sectorsPerClusterShift); + m_clusterMask = m_bytesPerCluster - 1; + // Set m_bitmapStart to first free cluster. + m_bitmapStart = 0; + bitmapFind(0, 1); + m_fatType = FAT_TYPE_EXFAT; + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ uint32_t ExFatPartition::rootLength() { uint32_t nc = chainSize(m_rootDirectoryCluster); return nc << bytesPerClusterShift(); diff --git a/src/ExFatLib/ExFatPartition.h b/src/ExFatLib/ExFatPartition.h index 91d4897a..4ca18a92 100644 --- a/src/ExFatLib/ExFatPartition.h +++ b/src/ExFatLib/ExFatPartition.h @@ -110,7 +110,7 @@ class FsCache { uint32_t m_sector; uint8_t m_cacheBuffer[512]; }; -//============================================================================= +//============================================================================== /** * \class ExFatPartition * \brief Access exFat partitions on raw file devices. @@ -119,15 +119,15 @@ class ExFatPartition { public: ExFatPartition() : m_fatType(0) {} /** \return the number of bytes in a cluster. */ - uint32_t bytesPerCluster() {return m_bytesPerCluster;} + uint32_t bytesPerCluster() const {return m_bytesPerCluster;} /** \return the power of two for bytesPerCluster. */ - uint8_t bytesPerClusterShift() { + uint8_t bytesPerClusterShift() const { return m_bytesPerSectorShift + m_sectorsPerClusterShift; } /** \return the number of bytes in a sector. */ - uint16_t bytesPerSector() {return m_bytesPerSector;} + uint16_t bytesPerSector() const {return m_bytesPerSector;} /** \return the power of two for bytesPerSector. */ - uint8_t bytesPerSectorShift() {return m_bytesPerSectorShift;} + uint8_t bytesPerSectorShift() const {return m_bytesPerSectorShift;} /** Clear the cache and returns a pointer to the cache. Not for normal apps. * \return A pointer to the cache buffer or zero if an error occurs. @@ -136,13 +136,13 @@ class ExFatPartition { return m_dataCache.clear(); } /** \return the cluster count for the partition. */ - uint32_t clusterCount() {return m_clusterCount;} + uint32_t clusterCount() const {return m_clusterCount;} /** \return the cluster heap start sector. */ - uint32_t clusterHeapStartSector() {return m_clusterHeapStartSector;} + uint32_t clusterHeapStartSector() const {return m_clusterHeapStartSector;} /** \return the FAT length in sectors */ - uint32_t fatLength() {return m_fatLength;} + uint32_t fatLength() const {return m_fatLength;} /** \return the FAT start sector number. */ - uint32_t fatStartSector() {return m_fatStartSector;} + uint32_t fatStartSector() const {return m_fatStartSector;} /** \return Type FAT_TYPE_EXFAT for exFAT partition or zero for error. */ uint8_t fatType() const {return m_fatType;} /** \return the free cluster count. */ @@ -158,17 +158,17 @@ class ExFatPartition { */ bool init(BlockDevice* dev, uint8_t part); /** \return the root directory start cluster number. */ - uint32_t rootDirectoryCluster() {return m_rootDirectoryCluster;} + uint32_t rootDirectoryCluster() const {return m_rootDirectoryCluster;} /** \return the root directory length. */ uint32_t rootLength(); /** \return the number of sectors in a cluster. */ - uint32_t sectorsPerCluster() {return 1UL << m_sectorsPerClusterShift;} + uint32_t sectorsPerCluster() const {return 1UL << m_sectorsPerClusterShift;} #ifndef DOXYGEN_SHOULD_SKIP_THIS // Use sectorsPerCluster(). blocksPerCluster() will be removed in the future. uint32_t blocksPerCluster() __attribute__ ((deprecated)) {return sectorsPerCluster();} //NOLINT #endif // DOXYGEN_SHOULD_SKIP_THIS /** \return the power of two for sectors per cluster. */ - uint8_t sectorsPerClusterShift() {return m_sectorsPerClusterShift;} + uint8_t sectorsPerClusterShift() const {return m_sectorsPerClusterShift;} //---------------------------------------------------------------------------- #ifndef DOXYGEN_SHOULD_SKIP_THIS void checkUpcase(print_t* pr); diff --git a/src/ExFatLib/ExFatVolume.cpp b/src/ExFatLib/ExFatVolume.cpp index 853c5299..0cb015ab 100644 --- a/src/ExFatLib/ExFatVolume.cpp +++ b/src/ExFatLib/ExFatVolume.cpp @@ -24,7 +24,7 @@ */ #include "ExFatVolume.h" ExFatVolume* ExFatVolume::m_cwv = nullptr; -//---------------------------------------------------------------------------- +//----------------------------------------------------------------------------- bool ExFatVolume::chdir(const ExChar_t* path) { ExFatFile dir; if (!dir.open(vwd(), path, O_RDONLY)) { @@ -36,6 +36,6 @@ bool ExFatVolume::chdir(const ExChar_t* path) { m_vwd = dir; return true; -fail: + fail: return false; } diff --git a/src/ExFatLib/ExFatVolume.h b/src/ExFatLib/ExFatVolume.h index 3e4a4edc..4d93e66b 100644 --- a/src/ExFatLib/ExFatVolume.h +++ b/src/ExFatLib/ExFatVolume.h @@ -26,7 +26,7 @@ #define ExFatVolume_h #include "ExFatPartition.h" #include "ExFatFile.h" -//============================================================================= +//============================================================================== /** * \class ExFatVolume * \brief exFAT volume. diff --git a/src/ExFatLib/upcase.cpp b/src/ExFatLib/upcase.cpp index cdc5142a..5edd9d8e 100644 --- a/src/ExFatLib/upcase.cpp +++ b/src/ExFatLib/upcase.cpp @@ -47,7 +47,7 @@ struct pair16 { uint16_t val; }; typedef struct pair16 pair16_t; -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ static const map16_t mapTable[] TABLE_MEM = { {0X0061, -32, 26}, {0X00E0, -32, 23}, @@ -104,7 +104,7 @@ static const map16_t mapTable[] TABLE_MEM = { {0XFF41, -32, 26}, }; const size_t MAP_DIM = sizeof(mapTable)/sizeof(map16_t); -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ static const pair16_t lookupTable[] TABLE_MEM = { {0X00FF, 0X0178}, {0X0180, 0X0243}, @@ -183,17 +183,7 @@ static const pair16_t lookupTable[] TABLE_MEM = { {0X2C76, 0X2C75}, }; const size_t LOOKUP_DIM = sizeof(lookupTable)/sizeof(pair16_t); - -//----------------------------------------------------------------------------- -uint16_t exFatHashName(const ExChar16_t* name, size_t n, uint16_t hash) { - for (size_t i = 0; i < n; i++) { - uint16_t c = toUpcase(name[i]); - hash = ((hash << 15) | (hash >> 1)) + (c & 0XFF); - hash = ((hash << 15) | (hash >> 1)) + (c >> 8); - } - return hash; -} -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ static size_t searchPair16(const pair16_t* table, size_t size, uint16_t key) { size_t left = 0; size_t right = size; @@ -208,29 +198,11 @@ static size_t searchPair16(const pair16_t* table, size_t size, uint16_t key) { } return left; } -//----------------------------------------------------------------------------- -uint16_t toUpcase(uint16_t chr) { - uint16_t i, first; - // Optimize for simple ASCII. - if (chr < 127) { - return chr - ('a' <= chr && chr <= 'z' ? 'a' - 'A' : 0); - } - i = searchPair16(reinterpret_cast(mapTable), MAP_DIM, chr); - first = readTable16(mapTable[i].base); - if (first <= chr && (chr - first) < readTable8(mapTable[i].count)) { - int8_t off = readTable8(mapTable[i].off); - if (off == 1) { - return chr - ((chr - first) & 1); - } - return chr + (off ? off : -0x1C60); - } - i = searchPair16(lookupTable, LOOKUP_DIM, chr); - if (readTable16(lookupTable[i].key) == chr) { - return readTable16(lookupTable[i].val); - } - return chr; +//------------------------------------------------------------------------------ +static char toUpper(char c) { + return c - ('a' <= c && c <= 'z' ? 'a' - 'A' : 0); } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool exFatCmpName(const DirName_t* unicode, const ExChar16_t* name, size_t offset, size_t n) { uint16_t u; @@ -242,11 +214,28 @@ bool exFatCmpName(const DirName_t* unicode, } return true; } -//----------------------------------------------------------------------------- -static char toUpper(char c) { - return c - ('a' <= c && c <= 'z' ? 'a' - 'A' : 0); +//------------------------------------------------------------------------------ +bool exFatCmpName(const DirName_t* unicode, + const char* name, size_t offset, size_t n) { + uint16_t u; + for (size_t i = 0; i < n; i++) { + u = getLe16(unicode->unicode + 2*i); + if (u >= 0x7F || toUpper(name[i + offset]) != toUpper(u)) { + return false; + } + } + return true; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ +uint16_t exFatHashName(const ExChar16_t* name, size_t n, uint16_t hash) { + for (size_t i = 0; i < n; i++) { + uint16_t c = toUpcase(name[i]); + hash = ((hash << 15) | (hash >> 1)) + (c & 0XFF); + hash = ((hash << 15) | (hash >> 1)) + (c >> 8); + } + return hash; +} +//------------------------------------------------------------------------------ uint16_t exFatHashName(const char* name, size_t n, uint16_t hash) { for (size_t i = 0; i < n; i++) { uint8_t c = name[i]; @@ -258,19 +247,29 @@ uint16_t exFatHashName(const char* name, size_t n, uint16_t hash) { } return hash; } -//----------------------------------------------------------------------------- -bool exFatCmpName(const DirName_t* unicode, - const char* name, size_t offset, size_t n) { - uint16_t u; - for (size_t i = 0; i < n; i++) { - u = getLe16(unicode->unicode + 2*i); - if (u >= 0x7F || toUpper(name[i + offset]) != toUpper(u)) { - return false; +//------------------------------------------------------------------------------ +uint16_t toUpcase(uint16_t chr) { + uint16_t i, first; + // Optimize for simple ASCII. + if (chr < 127) { + return chr - ('a' <= chr && chr <= 'z' ? 'a' - 'A' : 0); + } + i = searchPair16(reinterpret_cast(mapTable), MAP_DIM, chr); + first = readTable16(mapTable[i].base); + if (first <= chr && (chr - first) < readTable8(mapTable[i].count)) { + int8_t off = readTable8(mapTable[i].off); + if (off == 1) { + return chr - ((chr - first) & 1); } + return chr + (off ? off : -0x1C60); } - return true; + i = searchPair16(lookupTable, LOOKUP_DIM, chr); + if (readTable16(lookupTable[i].key) == chr) { + return readTable16(lookupTable[i].val); + } + return chr; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ uint32_t upcaseChecksum(uint16_t uc, uint32_t sum) { sum = (sum << 31) + (sum >> 1) + (uc & 0XFF); sum = (sum << 31) + (sum >> 1) + (uc >> 8); diff --git a/src/FatLib/FatDbg.cpp b/src/FatLib/FatDbg.cpp index 98a4bdea..a1b4e978 100644 --- a/src/FatLib/FatDbg.cpp +++ b/src/FatLib/FatDbg.cpp @@ -24,7 +24,6 @@ */ #include "FatVolume.h" #include "FatFile.h" -#include "../common/FsDateTime.h" #ifndef DOXYGEN_SHOULD_SKIP_THIS //------------------------------------------------------------------------------ static void printHex(print_t* pr, uint8_t h) { diff --git a/src/FatLib/FatFile.cpp b/src/FatLib/FatFile.cpp index d0aaf54a..1e066255 100644 --- a/src/FatLib/FatFile.cpp +++ b/src/FatLib/FatFile.cpp @@ -88,7 +88,7 @@ bool FatFile::addDirCluster() { m_curPosition += m_vol->bytesPerCluster(); return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -103,7 +103,7 @@ DirFat_t* FatFile::cacheDirEntry(uint8_t action) { } return pc->dir + (m_dirIndex & 0XF); -fail: + fail: return nullptr; } //------------------------------------------------------------------------------ @@ -116,7 +116,7 @@ bool FatFile::close() { //------------------------------------------------------------------------------ bool FatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) { // error if no clusters - if (m_firstCluster == 0) { + if (!isFile() || m_firstCluster == 0) { DBG_FAIL_MACRO; goto fail; } @@ -148,7 +148,7 @@ bool FatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) { } } -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -161,7 +161,7 @@ bool FatFile::createContiguous(const char* path, uint32_t size) { return true; } close(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -175,33 +175,6 @@ bool FatFile::createContiguous(FatFile* dirFile, return true; } close(); -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::preAllocate(uint32_t length) { - uint32_t need; - if (!length || !isWritable() || m_firstCluster) { - DBG_FAIL_MACRO; - goto fail; - } - need = 1 + ((length - 1) >> m_vol->bytesPerClusterShift()); - // allocate clusters - if (!m_vol->allocContiguous(need, &m_firstCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - m_fileSize = length; - -#if USE_FAT_FILE_FLAG_CONTIGUOUS - // Mark contiguous and insure sync() will update dir entry - m_flags |= FILE_FLAG_PREALLOCATE | FILE_FLAG_CONTIGUOUS | FILE_FLAG_DIR_DIRTY; -#else // USE_FAT_FILE_FLAG_CONTIGUOUS - // insure sync() will update dir entry - m_flags |= FILE_FLAG_DIR_DIRTY; -#endif // USE_FAT_FILE_FLAG_CONTIGUOUS - return sync(); - fail: return false; } @@ -223,7 +196,7 @@ bool FatFile::dirEntry(DirFat_t* dst) { memcpy(dst, dir, sizeof(DirFat_t)); return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -289,6 +262,47 @@ void FatFile::fsetpos(const fspos_t* pos) { m_curCluster = pos->cluster; } //------------------------------------------------------------------------------ +bool FatFile::getAccessDate(uint16_t* pdate) { + DirFat_t dir; + if (!dirEntry(&dir)) { + DBG_FAIL_MACRO; + goto fail; + } + *pdate = getLe16(dir.accessDate); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +bool FatFile::getCreateDateTime(uint16_t* pdate, uint16_t* ptime) { + DirFat_t dir; + if (!dirEntry(&dir)) { + DBG_FAIL_MACRO; + goto fail; + } + *pdate = getLe16(dir.createDate); + *ptime = getLe16(dir.createTime); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ +bool FatFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) { + DirFat_t dir; + if (!dirEntry(&dir)) { + DBG_FAIL_MACRO; + goto fail; + } + *pdate = getLe16(dir.modifyDate); + *ptime = getLe16(dir.modifyTime); + return true; + + fail: + return false; +} +//------------------------------------------------------------------------------ bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) { fname_t fname; FatFile tmpDir; @@ -327,7 +341,7 @@ bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) { } return mkdir(parent, &fname); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -397,10 +411,10 @@ bool FatFile::mkdir(FatFile* parent, fname_t* fname) { // write first sector return m_vol->cacheSync(); -fail: + fail: return false; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool FatFile::open(const char* path, oflag_t oflag) { return open(FatVolume::cwv(), path, oflag); } @@ -449,7 +463,7 @@ bool FatFile::open(FatFile* dirFile, const char* path, oflag_t oflag) { } return open(dirFile, &fname, oflag); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -574,7 +588,7 @@ bool FatFile::openCachedEntry(FatFile* dirFile, uint16_t dirIndex, } return true; -fail: + fail: m_attributes = FILE_ATTR_CLOSED; m_flags = 0; return false; @@ -629,7 +643,7 @@ bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) { } } -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -662,7 +676,34 @@ bool FatFile::openRoot(FatVolume* vol) { m_flags = FILE_FLAG_READ; return true; -fail: + fail: + return false; +} +//------------------------------------------------------------------------------ +bool FatFile::preAllocate(uint32_t length) { + uint32_t need; + if (!length || !isWritable() || m_firstCluster) { + DBG_FAIL_MACRO; + goto fail; + } + need = 1 + ((length - 1) >> m_vol->bytesPerClusterShift()); + // allocate clusters + if (!m_vol->allocContiguous(need, &m_firstCluster)) { + DBG_FAIL_MACRO; + goto fail; + } + m_fileSize = length; + +#if USE_FAT_FILE_FLAG_CONTIGUOUS + // Mark contiguous and insure sync() will update dir entry + m_flags |= FILE_FLAG_PREALLOCATE | FILE_FLAG_CONTIGUOUS | FILE_FLAG_DIR_DIRTY; +#else // USE_FAT_FILE_FLAG_CONTIGUOUS + // insure sync() will update dir entry + m_flags |= FILE_FLAG_DIR_DIRTY; +#endif // USE_FAT_FILE_FLAG_CONTIGUOUS + return sync(); + + fail: return false; } //------------------------------------------------------------------------------ @@ -790,7 +831,7 @@ int FatFile::read(void* buf, size_t nbyte) { } return nbyte - toRead; -fail: + fail: m_error |= READ_ERROR; return -1; } @@ -842,7 +883,7 @@ DirFat_t* FatFile::readDirCache(bool skipReadOk) { // return pointer to entry return reinterpret_cast(m_vol->cacheAddress()) + i; -fail: + fail: return nullptr; } //------------------------------------------------------------------------------ @@ -854,7 +895,7 @@ bool FatFile::remove(const char* path) { } return file.remove(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -966,7 +1007,7 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) { } return m_vol->cacheSync(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -1008,7 +1049,7 @@ bool FatFile::rmdir() { m_flags |= FILE_FLAG_WRITE; return remove(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -1083,7 +1124,7 @@ bool FatFile::rmRfStar() { } return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -1117,9 +1158,16 @@ bool FatFile::seekSet(uint32_t pos) { DBG_FAIL_MACRO; goto fail; } - // calculate cluster index for cur and new position - nCur = (m_curPosition - 1) >> (m_vol->bytesPerClusterShift()); + // calculate cluster index for new position nNew = (pos - 1) >> (m_vol->bytesPerClusterShift()); +#if USE_FAT_FILE_FLAG_CONTIGUOUS + if (isContiguous()) { + m_curCluster = m_firstCluster + nNew; + goto done; + } +#endif // USE_FAT_FILE_FLAG_CONTIGUOUS + // calculate cluster index for current position + nCur = (m_curPosition - 1) >> (m_vol->bytesPerClusterShift()); if (nNew < nCur || m_curPosition == 0) { // must follow chain from first cluster @@ -1135,12 +1183,12 @@ bool FatFile::seekSet(uint32_t pos) { } } -done: + done: m_curPosition = pos; m_flags &= ~FILE_FLAG_PREALLOCATE; return true; -fail: + fail: m_curCluster = tmp; return false; } @@ -1182,7 +1230,7 @@ bool FatFile::sync() { } DBG_FAIL_MACRO; -fail: + fail: m_error |= WRITE_ERROR; return false; } @@ -1233,7 +1281,7 @@ bool FatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, } return m_vol->cacheSync(); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -1436,7 +1484,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) { } return nbyte; -fail: + fail: // return for write error m_error |= WRITE_ERROR; return -1; diff --git a/src/FatLib/FatFile.h b/src/FatLib/FatFile.h index 6c708e56..eeffdaa5 100644 --- a/src/FatLib/FatFile.h +++ b/src/FatLib/FatFile.h @@ -151,10 +151,49 @@ class FatFile { } /** \return Directory entry index. */ uint16_t dirIndex() {return m_dirIndex;} + /** Get a file's access date. + * + * \param[out] pdate Packed date for directory entry. + * + * \return true for success or false for failure. + */ + bool getAccessDate(uint16_t* pdate); + /** Get a file's access date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime return zero since FAT has no time. + * + * This function is for comparability in FsFile. + * + * \return true for success or false for failure. + */ + bool getAccessDateTime(uint16_t* pdate, uint16_t* ptime) { + if (!getAccessDate(pdate)) { + return false; + } + *ptime = 0; + return true; + } + /** Get a file's create date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime); /** \return All error bits. */ uint8_t getError() { return m_error; } + /** Get a file's modify date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime); /** \return value of writeError */ bool getWriteError() { return isOpen() ? m_error & WRITE_ERROR : true; @@ -196,6 +235,8 @@ class FatFile { * \param[out] bgnSector the first sector address for the file. * \param[out] endSector the last sector address for the file. * + * Set the contiguous flag if the file is contiguous. + * The parameters may be nullptr to only set the flag. * \return true for success or false for failure. */ bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector); @@ -203,7 +244,7 @@ class FatFile { /** Create and open a new contiguous file of a specified size. * * \param[in] dirFile The directory where the file will be created. - * \param[in] path A path with a validfile name. + * \param[in] path A path with a valid file name. * \param[in] size The desired file size. * * \return true for success or false for failure. @@ -212,7 +253,7 @@ class FatFile { const char* path, uint32_t size); /** Create and open a new contiguous file of a specified size. * - * \param[in] path A path with a validfile name. + * \param[in] path A path with a valid file name. * \param[in] size The desired file size. * * \return true for success or false for failure. @@ -263,8 +304,8 @@ class FatFile { * Get a string from a file. * * fgets() reads bytes from a file into the array pointed to by \a str, until - * \a num - 1 bytes are read, or a delimiter is read and transferred to \a str, - * or end-of-file is encountered. The string is then terminated + * \a num - 1 bytes are read, or a delimiter is read and transferred to + * \a str, or end-of-file is encountered. The string is then terminated * with a null byte. * * fgets() deletes CR, '\\r', from the string. This insures only a '\\n' @@ -277,7 +318,8 @@ class FatFile { * \param[in] delim Optional set of delimiters. The default is "\n". * * \return For success fgets() returns the length of the string in \a str. - * If no data is read, fgets() returns zero for EOF or -1 if an error occurred. + * If no data is read, fgets() returns zero for EOF or -1 if an error + * occurred. */ int fgets(char* str, int num, char* delim = nullptr); @@ -287,7 +329,7 @@ class FatFile { } /** \return first sector of file or zero for empty file. */ uint32_t firstBlock() const {return firstSector();} - /** \return first sector of file or zero for empty file. */ + /** \return Address of first sector or zero for empty file. */ uint32_t firstSector() const; /** * Get a file's name followed by a zero byte. @@ -472,10 +514,12 @@ class FatFile { * O_CREAT - If the file exists, this flag has no effect except as noted * under O_EXCL below. Otherwise, the file shall be created * - * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. + * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file + * exists. * * O_TRUNC - If the file exists and is a regular file, and the file is - * successfully opened and is not read only, its length shall be truncated to 0. + * successfully opened and is not read only, its length shall be truncated + * to 0. * * WARNING: A given file must not be opened by more than one FatFile object * or file corruption may occur. @@ -873,7 +917,8 @@ class FatFile { * \return For success write() returns the number of bytes written, always * \a count. If an error occurs, write() returns -1. Possible errors * include write() is called before a file has been opened, write is called - * for a read-only file, device is full, a corrupt file system or an I/O error. + * for a read-only file, device is full, a corrupt file system or an I/O + * error. * */ size_t write(const void* buf, size_t count); diff --git a/src/FatLib/FatFileLFN.cpp b/src/FatLib/FatFileLFN.cpp index 80f94145..835bbb36 100644 --- a/src/FatLib/FatFileLFN.cpp +++ b/src/FatLib/FatFileLFN.cpp @@ -59,7 +59,7 @@ static uint16_t Bernstein(uint16_t hash, const char *str, size_t len) { * \param[in] i Index of character. * \return The 16-bit character. */ -static uint16_t lfnGetChar(DirLfn_t *ldir, uint8_t i) { +static uint16_t lfnGetChar(DirLfn_t* ldir, uint8_t i) { if (i < 5) { return getLe16(ldir->unicode1 + 2*i); } else if (i < 11) { @@ -70,7 +70,7 @@ static uint16_t lfnGetChar(DirLfn_t *ldir, uint8_t i) { return 0; } //------------------------------------------------------------------------------ -static bool lfnGetName(DirLfn_t *ldir, char* name, size_t n) { +static bool lfnGetName(DirLfn_t* ldir, char* name, size_t n) { uint8_t i; size_t k = 13*((ldir->order & 0X1F) - 1); for (i = 0; i < 13; i++) { @@ -104,7 +104,7 @@ inline bool lfnLegalChar(uint8_t c) { * \param[in] i Index of character. * \param[in] c The 16-bit character. */ -static void lfnPutChar(DirLfn_t *ldir, uint8_t i, uint16_t c) { +static void lfnPutChar(DirLfn_t* ldir, uint8_t i, uint16_t c) { if (i < 5) { setLe16(ldir->unicode1 + 2*i, c); } else if (i < 11) { @@ -114,7 +114,7 @@ static void lfnPutChar(DirLfn_t *ldir, uint8_t i, uint16_t c) { } } //------------------------------------------------------------------------------ -static void lfnPutName(DirLfn_t *ldir, const char* name, size_t n) { +static void lfnPutName(DirLfn_t* ldir, const char* name, size_t n) { size_t k = 13*((ldir->order & 0X1F) - 1); for (uint8_t i = 0; i < 13; i++, k++) { uint16_t c = k < n ? name[k] : k == n ? 0 : 0XFFFF; @@ -165,7 +165,7 @@ bool FatFile::getName(char* name, size_t size) { // Fall into fail. DBG_FAIL_MACRO; -fail: + fail: name[0] = 0; return false; } @@ -404,7 +404,7 @@ bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) { } } -found: + found: // Don't open if create only. if (oflag & O_EXCL) { DBG_FAIL_MACRO; @@ -412,7 +412,7 @@ bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) { } goto open; -create: + create: // don't create unless O_CREAT and write mode if (!(oflag & O_CREAT) || !isWriteMode(oflag)) { DBG_FAIL_MACRO; @@ -484,21 +484,26 @@ bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) { // Set base-name and extension lower case bits. dir->caseFlags = (FAT_CASE_LC_BASE | FAT_CASE_LC_EXT) & fname->flags; - // set timestamps + // Set timestamps. if (FsDateTime::callback) { // call user date/time function FsDateTime::callback(&date, &time, &ms10); - dir->createTimeMs = ms10; setLe16(dir->createDate, date); setLe16(dir->createTime, time); - setLe16(dir->accessDate, date); - setLe16(dir->modifyDate, date); - setLe16(dir->modifyTime, time);; + dir->createTimeMs = ms10; + } else { + setLe16(dir->createDate, FS_DEFAULT_DATE); + setLe16(dir->modifyDate, FS_DEFAULT_DATE); + setLe16(dir->accessDate, FS_DEFAULT_DATE); + if (FS_DEFAULT_TIME) { + setLe16(dir->createTime, FS_DEFAULT_TIME); + setLe16(dir->modifyTime, FS_DEFAULT_TIME); + } } // Force write of entry to device. dirFile->m_vol->cacheDirty(); -open: + open: // open entry in cache. if (!openCachedEntry(dirFile, curIndex, oflag, lfnOrd)) { DBG_FAIL_MACRO; @@ -506,7 +511,7 @@ bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) { } return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -553,7 +558,7 @@ size_t FatFile::printName(print_t* pr) { } return n; -fail: + fail: return 0; } //------------------------------------------------------------------------------ @@ -632,14 +637,14 @@ bool FatFile::remove() { // Fall into fail. DBG_FAIL_MACRO; -fail: + fail: return false; } //------------------------------------------------------------------------------ bool FatFile::lfnUniqueSfn(fname_t* fname) { const uint8_t FIRST_HASH_SEQ = 2; // min value is 2 uint8_t pos = fname->seqPos;; - DirFat_t *dir; + DirFat_t* dir; uint16_t hex; DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS)); @@ -685,10 +690,10 @@ bool FatFile::lfnUniqueSfn(fname_t* fname) { // fall inti fail - too many tries. DBG_FAIL_MACRO; -fail: + fail: return false; -done: + done: return true; } #endif // #if USE_LONG_FILE_NAMES diff --git a/src/FatLib/FatFilePrint.cpp b/src/FatLib/FatFilePrint.cpp index f5b132c8..158a59bc 100644 --- a/src/FatLib/FatFilePrint.cpp +++ b/src/FatLib/FatFilePrint.cpp @@ -121,38 +121,28 @@ bool FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) { } //------------------------------------------------------------------------------ size_t FatFile::printAccessDate(print_t* pr) { - DirFat_t dir; - if (!dirEntry(&dir)) { - DBG_FAIL_MACRO; - goto fail; + uint16_t date; + if (getAccessDate(&date)) { + return fsPrintDate(pr, date); } - return fsPrintDate(pr, getLe16(dir.accessDate)); - -fail: return 0; } //------------------------------------------------------------------------------ size_t FatFile::printCreateDateTime(print_t* pr) { - DirFat_t dir; - if (!dirEntry(&dir)) { - DBG_FAIL_MACRO; - goto fail; + uint16_t date; + uint16_t time; + if (getCreateDateTime(&date, &time)) { + return fsPrintDateTime(pr, date, time); } - return fsPrintDateTime(pr, getLe16(dir.createDate), getLe16(dir.createTime)); - -fail: return 0; } //------------------------------------------------------------------------------ size_t FatFile::printModifyDateTime(print_t* pr) { - DirFat_t dir; - if (!dirEntry(&dir)) { - DBG_FAIL_MACRO; - goto fail; + uint16_t date; + uint16_t time; + if (getModifyDateTime(&date, &time)) { + return fsPrintDateTime(pr, date, time); } - return fsPrintDateTime(pr, getLe16(dir.modifyDate), getLe16(dir.modifyTime)); - -fail: return 0; } //------------------------------------------------------------------------------ diff --git a/src/FatLib/FatFileSFN.cpp b/src/FatLib/FatFileSFN.cpp index ed9629c3..ccf0f0e5 100644 --- a/src/FatLib/FatFileSFN.cpp +++ b/src/FatLib/FatFileSFN.cpp @@ -31,7 +31,7 @@ bool FatFile::getSFN(char* name) { uint8_t j = 0; uint8_t lcBit = FAT_CASE_LC_BASE; - DirFat_t *dir; + DirFat_t* dir; if (!isOpen()) { DBG_FAIL_MACRO; @@ -67,7 +67,7 @@ bool FatFile::getSFN(char* name) { name[j] = 0; return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -79,7 +79,7 @@ size_t FatFile::printSFN(print_t* pr) { } return pr->write(name); -fail: + fail: return 0; } #if !USE_LONG_FILE_NAMES @@ -138,7 +138,7 @@ bool FatFile::parsePathName(const char* path, fname_t* fname, *ptr = path; return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -242,16 +242,21 @@ bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) { // Set base-name and extension lower case bits. dir->caseFlags = (FAT_CASE_LC_BASE | FAT_CASE_LC_EXT) & fname->flags; - // set timestamps + // Set timestamps. if (FsDateTime::callback) { // call user date/time function FsDateTime::callback(&date, &time, &ms10); - dir->createTimeMs = ms10; - setLe16(dir->createTime, time); - setLe16(dir->modifyTime, time); - setLe16(dir->accessDate, date); setLe16(dir->createDate, date); - setLe16(dir->modifyDate, date); + setLe16(dir->createTime, time); + dir->createTimeMs = ms10; + } else { + setLe16(dir->createDate, FS_DEFAULT_DATE); + setLe16(dir->modifyDate, FS_DEFAULT_DATE); + setLe16(dir->accessDate, FS_DEFAULT_DATE); + if (FS_DEFAULT_TIME) { + setLe16(dir->createTime, FS_DEFAULT_TIME); + setLe16(dir->modifyTime, FS_DEFAULT_TIME); + } } // Force write of entry to device. dirFile->m_vol->cacheDirty(); @@ -259,7 +264,7 @@ bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) { // open entry in cache. return openCachedEntry(dirFile, index, oflag, 0); -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -295,7 +300,7 @@ bool FatFile::remove() { // Write entry to device. return m_vol->cacheSync(); -fail: + fail: return false; } #endif // !USE_LONG_FILE_NAMES diff --git a/src/FatLib/FatFormatter.cpp b/src/FatLib/FatFormatter.cpp index fa7b1238..1ad018d3 100644 --- a/src/FatLib/FatFormatter.cpp +++ b/src/FatLib/FatFormatter.cpp @@ -35,7 +35,7 @@ const uint16_t SECTORS_PER_MB = 0X100000/BYTES_PER_SECTOR; const uint16_t FAT16_ROOT_ENTRY_COUNT = 512; const uint16_t FAT16_ROOT_SECTOR_COUNT = 32*FAT16_ROOT_ENTRY_COUNT/BYTES_PER_SECTOR; -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ #define PRINT_FORMAT_PROGRESS 1 #if !PRINT_FORMAT_PROGRESS #define writeMsg(str) @@ -44,7 +44,7 @@ const uint16_t FAT16_ROOT_SECTOR_COUNT = #else // PRINT_FORMAT_PROGRESS #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 rtn; m_dev = dev; @@ -80,7 +80,7 @@ bool FatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) { } return rtn; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool FatFormatter::initFatDir(uint8_t fatType, uint32_t sectorCount) { size_t n; memset(m_secBuf, 0, BYTES_PER_SECTOR); @@ -103,7 +103,7 @@ bool FatFormatter::initFatDir(uint8_t fatType, uint32_t sectorCount) { return m_dev->writeSector(m_fatStart, m_secBuf) && m_dev->writeSector(m_fatStart + m_fatSize, m_secBuf); } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ void FatFormatter::initPbs() { PbsFat_t* pbs = reinterpret_cast(m_secBuf); memset(m_secBuf, 0, BYTES_PER_SECTOR); @@ -128,7 +128,7 @@ void FatFormatter::initPbs() { // skip rest of bpb setLe16(pbs->signature, PBR_SIGNATURE); } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool FatFormatter::makeFat16() { uint32_t nc; uint32_t r; @@ -180,7 +180,7 @@ bool FatFormatter::makeFat16() { } return initFatDir(16, m_dataStart - m_fatStart); } -//----------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool FatFormatter::makeFat32() { uint32_t nc; uint32_t r; diff --git a/src/FatLib/FatPartition.cpp b/src/FatLib/FatPartition.cpp index 71a0a9cb..c46bb51a 100644 --- a/src/FatLib/FatPartition.cpp +++ b/src/FatLib/FatPartition.cpp @@ -46,7 +46,7 @@ cache_t* FatCache::read(uint32_t sector, uint8_t option) { m_status |= option & CACHE_STATUS_MASK; return &m_buffer; -fail: + fail: return nullptr; } @@ -69,7 +69,7 @@ bool FatCache::sync() { } return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -130,7 +130,7 @@ bool FatPartition::allocateCluster(uint32_t current, uint32_t* next) { *next = find; return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -195,7 +195,7 @@ bool FatPartition::allocContiguous(uint32_t count, uint32_t* firstCluster) { *firstCluster = bgnCluster; return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -266,7 +266,7 @@ int8_t FatPartition::fatGet(uint32_t cluster, uint32_t* value) { *value = next; return 1; -fail: + fail: return -1; } //------------------------------------------------------------------------------ @@ -343,7 +343,7 @@ bool FatPartition::fatPut(uint32_t cluster, uint32_t value) { goto fail; } -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -372,7 +372,7 @@ bool FatPartition::freeChain(uint32_t cluster) { return true; -fail: + fail: return false; } //------------------------------------------------------------------------------ @@ -434,7 +434,7 @@ int32_t FatPartition::freeClusterCount() { setFreeClusterCount(free); return free; -fail: + fail: return -1; } //------------------------------------------------------------------------------ @@ -462,7 +462,7 @@ bool FatPartition::init(BlockDevice* dev, uint8_t part) { } mbr = reinterpret_cast (cacheFetchData(0, FatCache::CACHE_FOR_READ)); - MbrPart_t *mp = mbr->part + part - 1; + MbrPart_t* mp = mbr->part + part - 1; if (!mbr || mp->type == 0 || (mp->boot != 0 && mp->boot != 0X80)) { DBG_FAIL_MACRO; @@ -533,6 +533,6 @@ bool FatPartition::init(BlockDevice* dev, uint8_t part) { } return true; -fail: + fail: return false; } diff --git a/src/FatLib/FatPartition.h b/src/FatLib/FatPartition.h index 6656f856..5cdbc86c 100644 --- a/src/FatLib/FatPartition.h +++ b/src/FatLib/FatPartition.h @@ -339,7 +339,7 @@ class FatPartition { bool cacheSyncData() { return m_cache.sync(); } - cache_t *cacheAddress() { + cache_t* cacheAddress() { return m_cache.buffer(); } uint32_t cacheSectorNumber() { diff --git a/src/FatLib/FatVolume.cpp b/src/FatLib/FatVolume.cpp index a9535e19..d6f59e2f 100644 --- a/src/FatLib/FatVolume.cpp +++ b/src/FatLib/FatVolume.cpp @@ -24,7 +24,7 @@ */ #include "FatVolume.h" FatVolume* FatVolume::m_cwv = nullptr; -//---------------------------------------------------------------------------- +//------------------------------------------------------------------------------ bool FatVolume::chdir(const char *path) { FatFile dir; if (!dir.open(vwd(), path, O_RDONLY)) { @@ -36,6 +36,6 @@ bool FatVolume::chdir(const char *path) { m_vwd = dir; return true; -fail: + fail: return false; } diff --git a/src/FsLib/FsFile.h b/src/FsLib/FsFile.h index 457f1444..bc574c3a 100644 --- a/src/FsLib/FsFile.h +++ b/src/FsLib/FsFile.h @@ -63,7 +63,7 @@ class FsBaseFile { m_xFile ? m_xFile->available() : 0; } - /** Set writeError to zero */ + /** Clear writeError. */ void clearWriteError() { if (m_fFile) m_fFile->clearWriteError(); if (m_xFile) m_xFile->clearWriteError(); @@ -74,6 +74,20 @@ class FsBaseFile { * \return true for success or false for failure. */ bool close(); + /** Check for contiguous file and return its raw sector range. + * + * \param[out] bgnSector the first sector address for the file. + * \param[out] endSector the last sector address for the file. + * + * Set contiguous flag for FAT16/FAT32 files. + * Parameters may be nullptr. + * + * \return true for success or false for failure. + */ + bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector) { + return m_fFile ? m_fFile->contiguousRange(bgnSector, endSector) : + m_xFile ? m_xFile->contiguousRange(bgnSector, endSector) : false; + } /** \return The current position for a file or directory. */ uint64_t curPosition() { return m_fFile ? m_fFile->curPosition() : @@ -135,6 +149,11 @@ class FsBaseFile { return m_fFile ? m_fFile->fileSize() : m_xFile ? m_xFile->fileSize() : 0; } + /** \return Address of first sector or zero for empty file. */ + uint32_t firstSector() { + return m_fFile ? m_fFile->firstSector() : + m_xFile ? m_xFile->firstSector() : 0; + } /** Ensure that any bytes written to the file are saved to the SD card. */ void flush() {sync();} /** set position for streams @@ -144,11 +163,44 @@ class FsBaseFile { if (m_fFile) m_fFile->fsetpos(pos); if (m_xFile) m_xFile->fsetpos(pos); } + /** Get a file's access date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getAccessDateTime(uint16_t* pdate, uint16_t* ptime) { + return m_fFile ? m_fFile->getAccessDateTime(pdate, ptime) : + m_xFile ? m_xFile->getAccessDateTime(pdate, ptime) : false; + } + /** Get a file's create date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime) { + return m_fFile ? m_fFile->getCreateDateTime(pdate, ptime) : + m_xFile ? m_xFile->getCreateDateTime(pdate, ptime) : false; + } /** \return All error bits. */ uint8_t getError() { return m_fFile ? m_fFile->getError() : m_xFile ? m_xFile->getError() : 0XFF; } + /** Get a file's Modify date and time. + * + * \param[out] pdate Packed date for directory entry. + * \param[out] ptime Packed time for directory entry. + * + * \return true for success or false for failure. + */ + bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime) { + return m_fFile ? m_fFile->getModifyDateTime(pdate, ptime) : + m_xFile ? m_xFile->getModifyDateTime(pdate, ptime) : false; + } /** * Get a file's name followed by a zero byte. * @@ -169,6 +221,15 @@ class FsBaseFile { return m_fFile ? m_fFile->getWriteError() : m_xFile ? m_xFile->getWriteError() : true; } + /** \return True if the file is contiguous. */ + bool isContiguous() { +#if USE_FAT_FILE_FLAG_CONTIGUOUS + return m_fFile ? m_fFile->isContiguous() : + m_xFile ? m_xFile->isContiguous() : false; +#else // USE_FAT_FILE_FLAG_CONTIGUOUS + return m_xFile ? m_xFile->isContiguous() : false; +#endif // USE_FAT_FILE_FLAG_CONTIGUOUS + } /** \return True if this is a directory else false. */ bool isDir() { return m_fFile ? m_fFile->isDir() : @@ -593,7 +654,7 @@ class FsBaseFile { * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive * OR of flags from the following list * - * T_ACCESS - Set the file's last access date. + * T_ACCESS - Set the file's last access date and time. * * T_CREATE - Set the file's creation date and time. * diff --git a/src/FsLib/FsVolume.h b/src/FsLib/FsVolume.h index 118b03cf..1cd85d36 100644 --- a/src/FsLib/FsVolume.h +++ b/src/FsLib/FsVolume.h @@ -230,7 +230,7 @@ class FsVolume { m_xVol ? m_xVol->rmdir(path) : false; } #if ENABLE_ARDUINO_SERIAL - /** List directory contents. + /** List directory contents. * \return true for success or false for failure. */ bool ls() { diff --git a/src/SdCard/SdSpiCard.cpp b/src/SdCard/SdSpiCard.cpp index 86ee92dd..81a90636 100644 --- a/src/SdCard/SdSpiCard.cpp +++ b/src/SdCard/SdSpiCard.cpp @@ -151,7 +151,7 @@ static uint8_t CRC7(const uint8_t* data, uint8_t n) { #if USE_SD_CRC == 1 // Shift based CRC-CCITT // uses the x^16,x^12,x^5,x^1 polynomial. -static uint16_t CRC_CCITT(const uint8_t *data, size_t n) { +static uint16_t CRC_CCITT(const uint8_t* data, size_t n) { uint16_t crc = 0; for (size_t i = 0; i < n; i++) { crc = (uint8_t)(crc >> 8) | (crc << 8); @@ -326,7 +326,7 @@ bool SdSpiCard::begin(SdSpiConfig spiConfig) { spiSetSckSpeed(spiConfig.maxSck); return true; -fail: + fail: spiStop(); return false; } @@ -363,7 +363,7 @@ uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) { spiSend(cmd | 0x40); // send argument - uint8_t *pa = reinterpret_cast(&arg); + uint8_t* pa = reinterpret_cast(&arg); for (int8_t i = 3; i >= 0; i--) { spiSend(pa[i]); } @@ -419,7 +419,7 @@ bool SdSpiCard::erase(uint32_t firstSector, uint32_t lastSector) { spiStop(); return true; -fail: + fail: spiStop(); return false; } @@ -458,7 +458,7 @@ bool SdSpiCard::isTimedOut(SdMillis_t startMS, SdMillis_t timeoutMS) { return (SysCall::curTimeMS() - startMS) > timeoutMS; } //------------------------------------------------------------------------------ -bool SdSpiCard::readData(uint8_t *dst) { +bool SdSpiCard::readData(uint8_t* dst) { return readData(dst, 512); } //------------------------------------------------------------------------------ @@ -501,13 +501,13 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) { #endif // USE_SD_CRC return true; -fail: + fail: spiStop(); return false; } //------------------------------------------------------------------------------ bool SdSpiCard::readOCR(uint32_t* ocr) { - uint8_t *p = reinterpret_cast(ocr); + uint8_t* p = reinterpret_cast(ocr); syncDevice(); if (cardCommand(CMD58, 0)) { error(SD_CARD_ERROR_CMD58); @@ -519,7 +519,7 @@ bool SdSpiCard::readOCR(uint32_t* ocr) { spiStop(); return true; -fail: + fail: spiStop(); return false; } @@ -538,7 +538,7 @@ bool SdSpiCard::readRegister(uint8_t cmd, void* buf) { spiStop(); return true; -fail: + fail: spiStop(); return false; } @@ -558,7 +558,7 @@ bool SdSpiCard::readSingle(uint32_t sector, uint8_t* dst) { spiStop(); return true; -fail: + fail: spiStop(); return false; } @@ -574,7 +574,7 @@ bool SdSpiCard::readStart(uint32_t sector) { // spiStop(); return true; -fail: + fail: spiStop(); return false; } @@ -591,16 +591,42 @@ bool SdSpiCard::readStatus(uint8_t* status) { spiStop(); return true; -fail: + fail: spiStop(); return false; } //------------------------------------------------------------------------------ -uint32_t SdSpiCard::sectorCount() { - csd_t csd; - return readCSD(&csd) ? sdCardCapacity(&csd) : 0; +bool SdSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) { +#if ENABLE_DEDICATED_SPI + if (m_curState != READ_STATE || sector != m_curSector) { + if (!syncDevice()) { + return false; + } + if (!SdSpiCard::readStart(sector)) { + return false; + } + m_curSector = sector; + m_curState = READ_STATE; + } + for (size_t i = 0; i < ns; i++, dst += 512) { + if (!readData(dst, 512)) { + return false; + } + } + m_curSector += ns; + return m_sharedSpi ? syncDevice() : true; +#else // ENABLE_DEDICATED_SPI + if (!readStart(sector)) { + return false; + } + for (size_t i = 0; i < ns; i++, dst += 512) { + if (!readData(dst, 512)) { + return false; + } + } + return readStop(); +#endif // ENABLE_DEDICATED_SPI } - //------------------------------------------------------------------------------ bool SdSpiCard::readStop() { if (cardCommand(CMD12, 0)) { @@ -610,11 +636,16 @@ bool SdSpiCard::readStop() { spiStop(); return true; -fail: + fail: spiStop(); return false; } //------------------------------------------------------------------------------ +uint32_t SdSpiCard::sectorCount() { + csd_t csd; + return readCSD(&csd) ? sdCardCapacity(&csd) : 0; +} +//------------------------------------------------------------------------------ void SdSpiCard::spiStart() { if (!m_spiActive) { spiActivate(); @@ -632,6 +663,22 @@ void SdSpiCard::spiStop() { } } //------------------------------------------------------------------------------ +bool SdSpiCard::syncDevice() { +#if ENABLE_DEDICATED_SPI + if (m_curState == READ_STATE) { + if (!SdSpiCard::readStop()) { + return false; + } + } else if (m_curState == WRITE_STATE) { + if (!SdSpiCard::writeStop()) { + return false; + } + } + m_curState = IDLE_STATE; +#endif // ENABLE_DEDICATED_SPI + return true; +} +//------------------------------------------------------------------------------ // wait for card to go not busy bool SdSpiCard::waitNotBusy(SdMillis_t timeoutMS) { SdMillis_t t0 = SysCall::curTimeMS(); @@ -654,6 +701,48 @@ bool SdSpiCard::waitNotBusy(SdMillis_t timeoutMS) { #endif // WDT_YIELD_TIME_MILLIS } //------------------------------------------------------------------------------ +bool SdSpiCard::writeData(const uint8_t* src) { + // wait for previous write to finish + DBG_BEGIN_TIME(DBG_WRITE_BUSY); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + error(SD_CARD_ERROR_WRITE_TIMEOUT); + goto fail; + } + DBG_END_TIME(DBG_WRITE_BUSY); + if (!writeData(WRITE_MULTIPLE_TOKEN, src)) { + goto fail; + } + return true; + + fail: + spiStop(); + return false; +} +//------------------------------------------------------------------------------ +// send one sector of data for write sector or write multiple sectors +bool SdSpiCard::writeData(uint8_t token, const uint8_t* src) { +#if USE_SD_CRC + uint16_t crc = CRC_CCITT(src, 512); +#else // USE_SD_CRC + uint16_t crc = 0XFFFF; +#endif // USE_SD_CRC + spiSend(token); + spiSend(src, 512); + spiSend(crc >> 8); + spiSend(crc & 0XFF); + + m_status = spiReceive(); + if ((m_status & DATA_RES_MASK) != DATA_RES_ACCEPTED) { + error(SD_CARD_ERROR_WRITE_DATA); + goto fail; + } + return true; + + fail: + spiStop(); + return false; +} +//------------------------------------------------------------------------------ bool SdSpiCard::writeSingle(uint32_t sector, const uint8_t* src) { // use address if not SDHC card if (type() != SD_CARD_TYPE_SDHC) { @@ -685,59 +774,11 @@ bool SdSpiCard::writeSingle(uint32_t sector, const uint8_t* src) { spiStop(); return true; -fail: + fail: spiStop(); return false; } //------------------------------------------------------------------------------ -bool SdSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) { -#if ENABLE_DEDICATED_SPI - if (m_curState != READ_STATE || sector != m_curSector) { - if (!syncDevice()) { - return false; - } - if (!SdSpiCard::readStart(sector)) { - return false; - } - m_curSector = sector; - m_curState = READ_STATE; - } - for (size_t i = 0; i < ns; i++, dst += 512) { - if (!readData(dst, 512)) { - return false; - } - } - m_curSector += ns; - return m_sharedSpi ? syncDevice() : true; -#else // ENABLE_DEDICATED_SPI - if (!readStart(sector)) { - return false; - } - for (size_t i = 0; i < ns; i++, dst += 512) { - if (!readData(dst, 512)) { - return false; - } - } - return readStop(); -#endif // ENABLE_DEDICATED_SPI -} -//------------------------------------------------------------------------------ -bool SdSpiCard::syncDevice() { -#if ENABLE_DEDICATED_SPI - if (m_curState == READ_STATE) { - if (!SdSpiCard::readStop()) { - return false; - } - } else if (m_curState == WRITE_STATE) { - if (!SdSpiCard::writeStop()) { - return false; - } - } - m_curState = IDLE_STATE; -#endif // ENABLE_DEDICATED_SPI - return true; -} -//------------------------------------------------------------------------------ bool SdSpiCard::writeSectors(uint32_t sector, const uint8_t* src, size_t ns) { #if ENABLE_DEDICATED_SPI if (m_curState != WRITE_STATE || m_curSector != sector) { @@ -774,48 +815,6 @@ bool SdSpiCard::writeSectors(uint32_t sector, const uint8_t* src, size_t ns) { #endif // ENABLE_DEDICATED_SPI } //------------------------------------------------------------------------------ -bool SdSpiCard::writeData(const uint8_t* src) { - // wait for previous write to finish - DBG_BEGIN_TIME(DBG_WRITE_BUSY); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_TIMEOUT); - goto fail; - } - DBG_END_TIME(DBG_WRITE_BUSY); - if (!writeData(WRITE_MULTIPLE_TOKEN, src)) { - goto fail; - } - return true; - -fail: - spiStop(); - return false; -} -//------------------------------------------------------------------------------ -// send one sector of data for write sector or write multiple sectors -bool SdSpiCard::writeData(uint8_t token, const uint8_t* src) { -#if USE_SD_CRC - uint16_t crc = CRC_CCITT(src, 512); -#else // USE_SD_CRC - uint16_t crc = 0XFFFF; -#endif // USE_SD_CRC - spiSend(token); - spiSend(src, 512); - spiSend(crc >> 8); - spiSend(crc & 0XFF); - - m_status = spiReceive(); - if ((m_status & DATA_RES_MASK) != DATA_RES_ACCEPTED) { - error(SD_CARD_ERROR_WRITE_DATA); - goto fail; - } - return true; - -fail: - spiStop(); - return false; -} -//------------------------------------------------------------------------------ bool SdSpiCard::writeStart(uint32_t sector) { // use address if not SDHC card if (type() != SD_CARD_TYPE_SDHC) { @@ -827,7 +826,7 @@ bool SdSpiCard::writeStart(uint32_t sector) { } return true; -fail: + fail: spiStop(); return false; } @@ -848,7 +847,7 @@ bool SdSpiCard::writeStart(uint32_t blockNumber, uint32_t eraseCount) { } return true; -fail: + fail: spiStop(); return false; } @@ -863,7 +862,7 @@ bool SdSpiCard::writeStop() { spiStop(); return true; -fail: + fail: error(SD_CARD_ERROR_STOP_TRAN); spiStop(); return false; diff --git a/src/SdCard/SdSpiCard.h b/src/SdCard/SdSpiCard.h index 21a69eac..3c09ec84 100644 --- a/src/SdCard/SdSpiCard.h +++ b/src/SdCard/SdSpiCard.h @@ -171,7 +171,7 @@ class SdSpiCard { * * \return true for success or false for failure. */ - bool readData(uint8_t *dst); + bool readData(uint8_t* dst); /** Read OCR register. * * \param[out] ocr Value of OCR register. diff --git a/src/SdCard/SdioCard.h b/src/SdCard/SdioCard.h index 88710491..d7ca687d 100644 --- a/src/SdCard/SdioCard.h +++ b/src/SdCard/SdioCard.h @@ -146,7 +146,7 @@ class SdioCard : public SdCardInterface { * * \return true for success or false for failure. */ - bool readData(uint8_t *dst); + bool readData(uint8_t* dst); /** Read OCR register. * * \param[out] ocr Value of OCR register. diff --git a/src/SdCard/SdioTeensy.cpp b/src/SdCard/SdioTeensy.cpp index e21e1f3c..8954c080 100644 --- a/src/SdCard/SdioTeensy.cpp +++ b/src/SdCard/SdioTeensy.cpp @@ -733,9 +733,9 @@ bool SdioCard::readCSD(csd_t* csd) { return true; } //------------------------------------------------------------------------------ -bool SdioCard::readData(uint8_t *dst) { +bool SdioCard::readData(uint8_t* dst) { DBG_IRQSTAT(); - uint32_t *p32 = reinterpret_cast(dst); + uint32_t* p32 = reinterpret_cast(dst); if (!(SDHC_PRSSTAT & SDHC_PRSSTAT_RTA)) { SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ; @@ -911,7 +911,7 @@ bool SdioCard::writeData(const uint8_t* src) { //------------------------------------------------------------------------------ bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) { if (m_sdioConfig.useDma()) { - uint8_t *ptr; + uint8_t* ptr; uint8_t aligned[512]; if (3 & (uint32_t)src) { ptr = aligned; diff --git a/src/SdCard/SdioTeensy.h b/src/SdCard/SdioTeensy.h index 8024838f..69573dc1 100644 --- a/src/SdCard/SdioTeensy.h +++ b/src/SdCard/SdioTeensy.h @@ -217,7 +217,7 @@ #define SDHC_MMCBOOT_BOOTMODE MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Boot Mode Select #define SDHC_MMCBOOT_BOOTACK MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Boot Ack Mode Select #define SDHC_MMCBOOT_DTOCVACK(n) MAKE_REG_MASK(0xF,0) //(uint32_t)(((n) & 0xF)<<0) // Boot ACK Time Out Counter Value -//#define SDHC_HOSTVER (*(volatile uint32_t *)0x400B10FC) // Host Controller Version +//#define SDHC_HOSTVER (*(volatile uint32_t*)0x400B10FC) // Host Controller Version #define CCM_ANALOG_PFD_528_PFD0_FRAC_MASK 0x3f #define CCM_ANALOG_PFD_528_PFD0_FRAC(n) ((n) & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) diff --git a/src/SdFat.h b/src/SdFat.h index 771fc52b..b7855ede 100644 --- a/src/SdFat.h +++ b/src/SdFat.h @@ -39,7 +39,7 @@ //------------------------------------------------------------------------------ /** SdFat version */ -#define SD_FAT_VERSION "2.0.0" +#define SD_FAT_VERSION "2.0.2" //============================================================================== /** * \class SdBase @@ -397,16 +397,22 @@ class SdFs : public SdBase { /** Select type for SdFat. */ typedef SdFat32 SdFat; /** Select type for File. */ +#if !defined(__has_include) || !__has_include() typedef File32 File; +#endif /** Select type for SdBaseFile. */ typedef FatFile SdBaseFile; #elif SDFAT_FILE_TYPE == 2 typedef SdExFat SdFat; +#if !defined(__has_include) || !__has_include() typedef ExFile File; +#endif typedef ExFatFile SdBaseFile; #elif SDFAT_FILE_TYPE == 3 typedef SdFs SdFat; +#if !defined(__has_include) || !__has_include() typedef FsFile File; +#endif typedef FsBaseFile SdBaseFile; #else // SDFAT_FILE_TYPE #error Invalid SDFAT_FILE_TYPE @@ -437,11 +443,11 @@ class SdFile : public PrintFile { * * // User gets date and time from GPS or real-time clock here * - * // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); + * // return date using FS_DATE macro to format fields + * *date = FS_DATE(year, month, day); * - * // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); + * // return time using FS_TIME macro to format fields + * *time = FS_TIME(hour, minute, second); * } * \endcode * diff --git a/src/SdFatConfig.h b/src/SdFatConfig.h index ac7b0902..aa9e6bb2 100644 --- a/src/SdFatConfig.h +++ b/src/SdFatConfig.h @@ -57,7 +57,7 @@ #define INCLUDE_SDIOS 0 //------------------------------------------------------------------------------ /** - * Set USE_FAT_FILE_FLAG_CONTIGUOUS nonzero to optimize access to + * Set USE_FAT_FILE_FLAG_CONTIGUOUS nonzero to optimize access to * contiguous files. */ #define USE_FAT_FILE_FLAG_CONTIGUOUS 1 @@ -73,6 +73,9 @@ #if defined(__AVR__) && FLASHEND < 0X8000 // 32K AVR boards. #define SDFAT_FILE_TYPE 1 +#elif defined(__arm__) +// ARM boards usually have plenty of memory +#define SDFAT_FILE_TYPE 3 #else // defined(__AVR__) && FLASHEND < 0X8000 // All other boards. #define SDFAT_FILE_TYPE 1 @@ -152,6 +155,24 @@ typedef uint8_t SdCsPin_t; */ #define USE_LONG_FILE_NAMES 1 //------------------------------------------------------------------------------ +/** + * Set the default file time stamp when a RTC callback is not used. + * A valid date and time is required by the FAT/exFAT standard. + * + * The default below is YYYY-01-01 00:00:00 midnight where YYYY is + * the compile year from the __DATE__ macro. This is easy to recognize + * as a placeholder for a correct date/time. + * + * The full compile date is: + * FS_DATE(compileYear(), compileMonth(), compileDay()) + * + * The full compile time is: + * FS_TIME(compileHour(), compileMinute(), compileSecond()) + */ +#define FS_DEFAULT_DATE FS_DATE(compileYear(), 1, 1) +/** 00:00:00 midnight */ +#define FS_DEFAULT_TIME FS_TIME(0, 0, 0) +//------------------------------------------------------------------------------ /** * If CHECK_FLASH_PROGRAMMING is zero, overlap of single sector flash * programming and other operations will be allowed for faster write diff --git a/src/SpiDriver/SdSpiArtemis.cpp b/src/SpiDriver/SdSpiArtemis.cpp index 4440ca11..954db6c8 100644 --- a/src/SpiDriver/SdSpiArtemis.cpp +++ b/src/SpiDriver/SdSpiArtemis.cpp @@ -46,7 +46,7 @@ uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); } //------------------------------------------------------------------------------ -uint8_t SdSpiArduinoDriver::receive(uint8_t *buf, size_t count) { +uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) { m_spi->transferIn(buf, count); return 0; } @@ -55,7 +55,7 @@ void SdSpiArduinoDriver::send(uint8_t data) { m_spi->transfer(data); } //------------------------------------------------------------------------------ -void SdSpiArduinoDriver::send(const uint8_t *buf, size_t count) { +void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) { // If not a multiple of four. Command with CRC used six byte send. while (count%4) { send(*buf++); diff --git a/src/SpiDriver/SdSpiBaseClass.h b/src/SpiDriver/SdSpiBaseClass.h index 3d042d5d..19573276 100644 --- a/src/SpiDriver/SdSpiBaseClass.h +++ b/src/SpiDriver/SdSpiBaseClass.h @@ -36,7 +36,7 @@ class SdSpiBaseClass { public: /** Activate SPI hardware. */ virtual void activate() {} - /** Initialize the SPI bus. + /** Initialize the SPI bus. * * \param[in] config SPI configuration. */ diff --git a/src/common/BlockDeviceInterface.h b/src/common/BlockDeviceInterface.h index f4be54bb..c478a16c 100644 --- a/src/common/BlockDeviceInterface.h +++ b/src/common/BlockDeviceInterface.h @@ -39,7 +39,7 @@ class BlockDeviceInterface { public: virtual ~BlockDeviceInterface() {} /** - * Read a 512 byte sector. + * Read a sector. * * \param[in] sector Logical sector to be read. * \param[out] dst Pointer to the location that will receive the data. @@ -48,7 +48,7 @@ class BlockDeviceInterface { virtual bool readSector(uint32_t sector, uint8_t* dst) = 0; #if USE_MULTI_SECTOR_IO /** - * Read multiple 512 byte sectors. + * Read multiple sectors. * * \param[in] sector Logical sector to be read. * \param[in] ns Number of sectors to be read. @@ -66,7 +66,7 @@ class BlockDeviceInterface { virtual bool syncDevice() = 0; /** - * Writes a 512 byte sector. + * Writes a sector. * * \param[in] sector Logical sector to be written. * \param[in] src Pointer to the location of the data to be written. @@ -75,7 +75,7 @@ class BlockDeviceInterface { virtual bool writeSector(uint32_t sector, const uint8_t* src) = 0; #if USE_MULTI_SECTOR_IO /** - * Write multiple 512 byte sectors. + * Write multiple sectors. * * \param[in] sector Logical sector to be written. * \param[in] ns Number of sectors to be written. diff --git a/src/common/CompileDateTime.h b/src/common/CompileDateTime.h new file mode 100644 index 00000000..829dd221 --- /dev/null +++ b/src/common/CompileDateTime.h @@ -0,0 +1,74 @@ +/** + * 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 CompileDateTime_h +#define CompileDateTime_h +// Note - these functions will compile to a few bytes +// since they are evaluated at compile time. + +/** \return year field of the __DATE__ macro. */ +constexpr uint16_t compileYear() { + return 1000*(__DATE__[7] - '0') + + 100*(__DATE__[8] - '0') + + 10*(__DATE__[9] - '0') + + (__DATE__[10] - '0'); +} +/** \return true if str equals the month field of the __DATE__ macro. */ +constexpr bool compileMonthIs(const char* str) { + return __DATE__[0] == str[0] + && __DATE__[1] == str[1] + && __DATE__[2] == str[2]; +} +/** \return month field of the __DATE__ macro. */ +constexpr uint8_t compileMonth() { + return compileMonthIs("Jan") ? 1 : + compileMonthIs("Feb") ? 2 : + compileMonthIs("Mar") ? 3 : + compileMonthIs("Apr") ? 4 : + compileMonthIs("May") ? 5 : + compileMonthIs("Jun") ? 6 : + compileMonthIs("Jul") ? 7 : + compileMonthIs("Aug") ? 8 : + compileMonthIs("Sep") ? 9 : + compileMonthIs("Oct") ? 10 : + compileMonthIs("Nov") ? 11 : + compileMonthIs("Dec") ? 12 : 0; +} +/** \return day field of the __DATE__ macro. */ +constexpr uint8_t compileDay() { + return 10*(__DATE__[4] == ' ' ? 0 : __DATE__[4] - '0') + (__DATE__[5] - '0'); +} +/** \return hour field of the __TIME__ macro. */ +constexpr uint8_t compileHour() { + return 10*(__TIME__[0] - '0') + __TIME__[1] - '0'; +} +/** \return minute field of the __TIME__ macro. */ +constexpr uint8_t compileMinute() { + return 10*(__TIME__[3] - '0') + __TIME__[4] - '0'; +} +/** \return second field of the __TIME__ macro. */ +constexpr uint8_t compileSecond() { + return 10*(__TIME__[6] - '0') + __TIME__[7] - '0'; +} +#endif // CompileDateTime_h diff --git a/src/common/FmtNumber.cpp b/src/common/FmtNumber.cpp index 450b31c9..fcc9e549 100644 --- a/src/common/FmtNumber.cpp +++ b/src/common/FmtNumber.cpp @@ -511,6 +511,6 @@ float scanFloat(const char* str, const char** ptr) { v = scale10(static_cast(fract), fracExp); return neg ? -v : v; -fail: + fail: return 0; } diff --git a/src/common/FsDateTime.cpp b/src/common/FsDateTime.cpp index 2c7b1efa..5faae531 100644 --- a/src/common/FsDateTime.cpp +++ b/src/common/FsDateTime.cpp @@ -43,7 +43,7 @@ namespace FsDateTime { callback2 = dateTime; } void setCallback( - void (*dateTime)(uint16_t* date, uint16_t* time, uint8_t *ms10)) { + void (*dateTime)(uint16_t* date, uint16_t* time, uint8_t* ms10)) { callback = dateTime; } } // namespace FsDateTime diff --git a/src/common/FsDateTime.h b/src/common/FsDateTime.h index 1611ba87..3bc49cec 100644 --- a/src/common/FsDateTime.h +++ b/src/common/FsDateTime.h @@ -25,23 +25,26 @@ #ifndef FsDateTime_h #define FsDateTime_h #include +#include "CompileDateTime.h" #include "SysCall.h" + /** Backward compatible definition. */ #define FAT_DATE(y, m, d) FS_DATE(y, m, d) /** Backward compatible definition. */ #define FAT_TIME(h, m, s) FS_TIME(h, m, s) + /** Date time callback */ namespace FsDateTime { /** Date time callback. */ extern void (*callback)(uint16_t* date, uint16_t* time, uint8_t* ms10); /** Date time callback. */ extern void (*callback2)(uint16_t* date, uint16_t* time); - /** Cancel callback */ + /** Cancel callback. */ void clearCallback(); - /** Set the date/time callback function + /** Set the date/time callback function. * - * \param[in] dateTime The user's call back function. The callback + * \param[in] dateTime The user's call back function. The callback. * function is of the form: * * \code @@ -49,13 +52,13 @@ namespace FsDateTime { * uint16_t year; * uint8_t month, day, hour, minute, second; * - * // User gets date and time from GPS or real-time clock here + * // User gets date and time from GPS or real-time clock here. * - * // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); + * // Return date using FS_DATE macro to format fields. + * *date = FS_DATE(year, month, day); * - * // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); + * // Return time using FS_TIME macro to format fields. + * *time = FS_TIME(hour, minute, second); * } * \endcode * @@ -66,7 +69,7 @@ namespace FsDateTime { * */ void setCallback(void (*dateTime)(uint16_t* date, uint16_t* time)); - /** Set the date/time callback function + /** Set the date/time callback function. * * \param[in] dateTime The user's call back function. The callback * function is of the form: @@ -76,15 +79,20 @@ namespace FsDateTime { * uint16_t year; * uint8_t month, day, hour, minute, second; * - * // User gets date and time from GPS or real-time clock here + * // User gets date and time from GPS or real-time clock here. * - * // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); + * // Return date using FS_DATE macro to format fields + * *date = FS_DATE(year, month, day); * - * // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); + * // Return time using FS_TIME macro to format fields + * *time = FS_TIME(hour, minute, second); * - * *ms10 = + * // Return tenths of milliseconds since last even second. + * // The granularity of the seconds part of FS_TIME is 2 seconds so + * // this field is a count of tenths of a second and its valid value + * // range is 0-199 inclusive. + * // For a simple RTC return 100*(seconds & 1). + * *ms10 = * } * \endcode * @@ -95,8 +103,9 @@ namespace FsDateTime { * */ void setCallback( - void (*dateTime)(uint16_t* date, uint16_t* time, uint8_t *ms10)); + void (*dateTime)(uint16_t* date, uint16_t* time, uint8_t* ms10)); } // namespace FsDateTime + /** date field for directory entry * \param[in] year [1980,2107] * \param[in] month [1,12] @@ -109,6 +118,11 @@ static inline uint16_t FS_DATE(uint16_t year, uint8_t month, uint8_t day) { return year > 127 || month > 12 || day > 31 ? 0 : year << 9 | month << 5 | day; } +/** year part of FAT directory date field + * \param[in] fatDate Date in packed dir format. + * + * \return Extracted year [1980,2107] + */ static inline uint16_t FS_YEAR(uint16_t fatDate) { return 1980 + (fatDate >> 9); } diff --git a/src/common/PrintBasic.h b/src/common/PrintBasic.h index e341cfb5..42e82926 100644 --- a/src/common/PrintBasic.h +++ b/src/common/PrintBasic.h @@ -138,7 +138,7 @@ class PrintBasic { } virtual size_t write(uint8_t b) = 0; - virtual size_t write(const uint8_t *buffer, size_t size) { + 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; @@ -146,7 +146,7 @@ class PrintBasic { return i; } size_t write(const char *buffer, size_t size) { - return write((const uint8_t *)buffer, size); + return write((const uint8_t*)buffer, size); } protected: diff --git a/src/common/SysCall.h b/src/common/SysCall.h index cfae1e34..bad84045 100644 --- a/src/common/SysCall.h +++ b/src/common/SysCall.h @@ -79,7 +79,10 @@ inline SdMillis_t SysCall::curTimeMS() { //------------------------------------------------------------------------------ #if defined(PLATFORM_ID) // Only defined if a Particle device inline void SysCall::yield() { - Particle.process(); + // 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() { diff --git a/src/iostream/StdioStream.cpp b/src/iostream/StdioStream.cpp index 0cbc0306..cc36cb69 100644 --- a/src/iostream/StdioStream.cpp +++ b/src/iostream/StdioStream.cpp @@ -146,7 +146,7 @@ bool StdioStream::fopen(const char* path, const char* mode) { m_p = m_buf; return true; -fail: + fail: m_status = 0; return false; } @@ -216,7 +216,7 @@ int StdioStream::fseek(int32_t offset, int origin) { m_p = m_buf; return 0; -fail: + fail: return EOF; } //------------------------------------------------------------------------------ diff --git a/src/iostream/StreamBaseClass.cpp b/src/iostream/StreamBaseClass.cpp index 1571bd11..67cf6bc5 100644 --- a/src/iostream/StreamBaseClass.cpp +++ b/src/iostream/StreamBaseClass.cpp @@ -92,7 +92,7 @@ void StreamBaseClass::open(const char* path, ios::openmode mode) { clear(); return; -fail: + fail: StreamBaseFile::close(); setstate(failbit); return; diff --git a/src/iostream/bufstream.h b/src/iostream/bufstream.h index eb31eca4..62218863 100644 --- a/src/iostream/bufstream.h +++ b/src/iostream/bufstream.h @@ -66,7 +66,7 @@ class ibufstream : public istream { setstate(eofbit); return -1; } - void getpos(pos_t *pos) { + void getpos(pos_t* pos) { pos->position = m_pos; } bool seekoff(off_type off, seekdir way) { @@ -81,7 +81,7 @@ class ibufstream : public istream { } return false; } - void setpos(pos_t *pos) { + void setpos(pos_t* pos) { m_pos = pos->position; } pos_type tellpos() { diff --git a/src/iostream/fstream.h b/src/iostream/fstream.h index 0e3d8d93..9686d45f 100644 --- a/src/iostream/fstream.h +++ b/src/iostream/fstream.h @@ -25,7 +25,7 @@ /** * \file * \brief iostreams for files. - */ + */ #ifndef fstream_h #define fstream_h #include "iostream.h" @@ -41,7 +41,7 @@ class StreamBaseClass : protected StreamBaseFile, virtual public ios { } /* Internal do not use * \return mode - */ + */ int16_t getch(); bool getWriteError() { return StreamBaseFile::getWriteError(); diff --git a/src/iostream/istream.cpp b/src/iostream/istream.cpp index 2aae33ed..8c7c5cc9 100644 --- a/src/iostream/istream.cpp +++ b/src/iostream/istream.cpp @@ -216,7 +216,7 @@ bool istream::getDouble(double* value) { *value = neg ? -v : v; return true; -fail: + fail: // error restore position to last good place setpos(&endPos); setstate(failbit); diff --git a/src/iostream/ostream.cpp b/src/iostream/ostream.cpp index 05d1b049..9ed9b70f 100644 --- a/src/iostream/ostream.cpp +++ b/src/iostream/ostream.cpp @@ -41,17 +41,6 @@ void ostream::fill_not_left(unsigned len) { } } //------------------------------------------------------------------------------ -char* ostream::fmtNum(uint32_t n, char *ptr, uint8_t base) { - char a = flags() & uppercase ? 'A' - 10 : 'a' - 10; - do { - uint32_t m = n; - n /= base; - char c = m - base * n; - *--ptr = c < 10 ? c + '0' : c + a; - } while (n); - return ptr; -} -//------------------------------------------------------------------------------ void ostream::putBool(bool b) { if (flags() & boolalpha) { if (b) { @@ -118,7 +107,7 @@ void ostream::putDouble(double n) { } do_fill(len); } else { - // do fill for internal or right + // do fill for right fill_not_left(len); if (sign) { *--str = sign; @@ -138,44 +127,12 @@ void ostream::putDouble(double n) { //------------------------------------------------------------------------------ void ostream::putNum(int32_t n) { bool neg = n < 0 && flagsToBase() == 10; - if (neg) { - n = -n; - } - putNum(n, neg); + putNum ((uint32_t)(neg ? -n : n), neg); } //------------------------------------------------------------------------------ -void ostream::putNum(uint32_t n, bool neg) { - char buf[13]; - char* ptr = buf + sizeof(buf) - 1; - char* num; - char* str; - uint8_t base = flagsToBase(); - *ptr = '\0'; - str = num = fmtNum(n, ptr, base); - if (base == 10) { - if (neg) { - *--str = '-'; - } else if (flags() & showpos) { - *--str = '+'; - } - } else if (flags() & showbase) { - if (flags() & hex) { - *--str = flags() & uppercase ? 'X' : 'x'; - } - *--str = '0'; - } - uint8_t len = ptr - str; - fmtflags adj = flags() & adjustfield; - if (adj == internal) { - while (str < num) { - putch(*str++); - } - } - if (adj != left) { - do_fill(len); - } - putstr(str); - do_fill(len); +void ostream::putNum(int64_t n) { + bool neg = n < 0 && flagsToBase() == 10; + putNum ((uint64_t)(neg ? -n : n), neg); } //------------------------------------------------------------------------------ void ostream::putPgm(const char* str) { diff --git a/src/iostream/ostream.h b/src/iostream/ostream.h index 52771f3b..09f501c4 100644 --- a/src/iostream/ostream.h +++ b/src/iostream/ostream.h @@ -183,6 +183,22 @@ class ostream : public virtual ios { putNum((uint32_t)arg); return *this; } + /** Output signed long long + * \param[in] arg value to output + * \return the stream + */ + ostream &operator<< (long long arg) { // NOLINT + putNum((int64_t)arg); + return *this; + } + /** Output unsigned long long + * \param[in] arg value to output + * \return the stream + */ + ostream &operator<< (unsigned long long arg) { // NOLINT + putNum((uint64_t)arg); + return *this; + } /** Output pointer * \param[in] arg value to output * \return the stream @@ -266,19 +282,67 @@ class ostream : public virtual ios { virtual bool seekoff(off_type pos, seekdir way) = 0; virtual bool seekpos(pos_type pos) = 0; virtual bool sync() = 0; - virtual pos_type tellpos() = 0; /// @endcond private: void do_fill(unsigned len); void fill_not_left(unsigned len); - char* fmtNum(uint32_t n, char *ptr, uint8_t base); void putBool(bool b); void putChar(char c); void putDouble(double n); - void putNum(uint32_t n, bool neg = false); void putNum(int32_t n); + void putNum(int64_t n); + void putNum(uint32_t n) {putNum(n, false);} + void putNum(uint64_t n) {putNum(n, false);} void putPgm(const char* str); void putStr(const char* str); + + template + char* fmtNum(T n, char *ptr, uint8_t base) { + char a = flags() & uppercase ? 'A' - 10 : 'a' - 10; + do { + T m = n; + n /= base; + char c = m - base * n; + *--ptr = c < 10 ? c + '0' : c + a; + } while (n); + return ptr; + } + + template + void putNum(T n, bool neg) { + char buf[(8*sizeof(T) + 2)/3 + 2]; + char* ptr = buf + sizeof(buf) - 1; + char* num; + char* str; + uint8_t base = flagsToBase(); + *ptr = '\0'; + str = num = fmtNum(n, ptr, base); + if (base == 10) { + if (neg) { + *--str = '-'; + } else if (flags() & showpos) { + *--str = '+'; + } + } else if (flags() & showbase) { + if (flags() & hex) { + *--str = flags() & uppercase ? 'X' : 'x'; + } + *--str = '0'; + } + uint8_t len = ptr - str; + fmtflags adj = flags() & adjustfield; + if (adj == internal) { + while (str < num) { + putch(*str++); + } + do_fill(len); + } else { + // do fill for right + fill_not_left(len); + } + putstr(str); + do_fill(len); + } }; #endif // ostream_h