浏览代码

Commit changes from SdFat-beta

Bill Greiman 8 年之前
父节点
当前提交
3163b54416
共有 100 个文件被更改,包括 2759 次插入1207 次删除
  1. 2 32
      README.md
  2. 18 16
      SdFat/MainPage/SdFatmainpage.h
  3. 0 67
      SdFat/SdFatUtil.h
  4. 0 171
      SdFat/SdSpiSTM32F1.cpp
  5. 0 71
      SdFat/SdVolume.h
  6. 16 9
      SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino
  7. 10 4
      SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino
  8. 5 2
      SdFat/examples/#attic/HelloWorld/HelloWorld.ino
  9. 4 4
      SdFat/examples/#attic/MiniSerial/MiniSerial.ino
  10. 15 11
      SdFat/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino
  11. 5 1
      SdFat/examples/#attic/SD_Size/SD_Size.ino
  12. 7 3
      SdFat/examples/#attic/SdFatSize/SdFatSize.ino
  13. 7 4
      SdFat/examples/#attic/StreamParseInt/StreamParseInt.ino
  14. 9 5
      SdFat/examples/#attic/append/append.ino
  15. 9 5
      SdFat/examples/#attic/average/average.ino
  16. 17 8
      SdFat/examples/#attic/benchSD/benchSD.ino
  17. 6 2
      SdFat/examples/#attic/bufstream/bufstream.ino
  18. 6 3
      SdFat/examples/#attic/cin_cout/cin_cout.ino
  19. 8 4
      SdFat/examples/#attic/eventlog/eventlog.ino
  20. 11 7
      SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino
  21. 6 3
      SdFat/examples/#attic/readlog/readlog.ino
  22. 7 1
      SdFat/examples/#attic/readme.txt
  23. 16 14
      SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino
  24. 18 12
      SdFat/examples/LongFileName/LongFileName.ino
  25. 53 22
      SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino
  26. 16 6
      SdFat/examples/OpenNext/OpenNext.ino
  27. 12 8
      SdFat/examples/PrintBenchmark/PrintBenchmark.ino
  28. 20 11
      SdFat/examples/QuickStart/QuickStart.ino
  29. 70 64
      SdFat/examples/RawWrite/RawWrite.ino
  30. 139 0
      SdFat/examples/ReadCsvArray/ReadCsvArray.ino
  31. 120 0
      SdFat/examples/ReadCsvStream/ReadCsvStream.ino
  32. 4 3
      SdFat/examples/ReadWrite/ReadWrite.ino
  33. 9 5
      SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino
  34. 28 13
      SdFat/examples/SdFormatter/SdFormatter.ino
  35. 16 9
      SdFat/examples/SdInfo/SdInfo.ino
  36. 14 4
      SdFat/examples/SoftwareSpi/SoftwareSpi.ino
  37. 18 15
      SdFat/examples/StdioBench/StdioBench.ino
  38. 17 14
      SdFat/examples/ThreeCards/ThreeCards.ino
  39. 9 7
      SdFat/examples/Timestamp/Timestamp.ino
  40. 14 10
      SdFat/examples/TwoCards/TwoCards.ino
  41. 81 0
      SdFat/examples/VolumeFreeSpace/VolumeFreeSpace.ino
  42. 32 15
      SdFat/examples/bench/bench.ino
  43. 14 7
      SdFat/examples/dataLogger/dataLogger.ino
  44. 33 28
      SdFat/examples/directoryFunctions/directoryFunctions.ino
  45. 9 3
      SdFat/examples/fgets/fgets.ino
  46. 5 2
      SdFat/examples/formatting/formatting.ino
  47. 10 5
      SdFat/examples/getline/getline.ino
  48. 192 95
      SdFat/examples/readCSV/readCSV.ino
  49. 9 5
      SdFat/examples/rename/rename.ino
  50. 38 0
      SdFat/examples/wipe/wipe.ino
  51. 9 0
      SdFat/library.properties
  52. 0 0
      SdFat/src/FatLib/ArduinoFiles.h
  53. 10 2
      SdFat/src/FatLib/ArduinoStream.h
  54. 0 0
      SdFat/src/FatLib/FatApiConstants.h
  55. 4 4
      SdFat/src/FatLib/FatFile.cpp
  56. 1 8
      SdFat/src/FatLib/FatFile.h
  57. 0 0
      SdFat/src/FatLib/FatFileLFN.cpp
  58. 0 0
      SdFat/src/FatLib/FatFilePrint.cpp
  59. 0 0
      SdFat/src/FatLib/FatFileSFN.cpp
  60. 10 1
      SdFat/src/FatLib/FatFileSystem.h
  61. 0 0
      SdFat/src/FatLib/FatLib.h
  62. 2 2
      SdFat/src/FatLib/FatLibConfig.h
  63. 122 0
      SdFat/src/FatLib/FatStructs.h
  64. 16 0
      SdFat/src/FatLib/FatVolume.cpp
  65. 22 6
      SdFat/src/FatLib/FatVolume.h
  66. 0 0
      SdFat/src/FatLib/FmtNumber.cpp
  67. 0 0
      SdFat/src/FatLib/FmtNumber.h
  68. 6 90
      SdFat/src/FatLib/StdioStream.cpp
  69. 2 10
      SdFat/src/FatLib/StdioStream.h
  70. 67 0
      SdFat/src/FatLib/SysCall.h
  71. 4 0
      SdFat/src/FatLib/bufstream.h
  72. 0 0
      SdFat/src/FatLib/fstream.cpp
  73. 0 0
      SdFat/src/FatLib/fstream.h
  74. 0 0
      SdFat/src/FatLib/ios.h
  75. 0 0
      SdFat/src/FatLib/iostream.h
  76. 10 0
      SdFat/src/FatLib/istream.cpp
  77. 0 0
      SdFat/src/FatLib/istream.h
  78. 0 0
      SdFat/src/FatLib/ostream.cpp
  79. 2 26
      SdFat/src/FatLib/ostream.h
  80. 54 0
      SdFat/src/FreeStack.h
  81. 1 1
      SdFat/src/MinimumSerial.cpp
  82. 1 1
      SdFat/src/MinimumSerial.h
  83. 21 20
      SdFat/src/SdFat.cpp
  84. 60 41
      SdFat/src/SdFat.h
  85. 67 15
      SdFat/src/SdFatConfig.h
  86. 2 12
      SdFat/src/SdFatUtil.cpp
  87. 35 0
      SdFat/src/SdFatUtil.h
  88. 378 0
      SdFat/src/SdSpiCard/DigitalPin.h
  89. 9 5
      SdFat/src/SdSpiCard/SdInfo.h
  90. 85 44
      SdFat/src/SdSpiCard/SdSpi.h
  91. 81 65
      SdFat/src/SdSpiCard/SdSpiCard.cpp
  92. 37 16
      SdFat/src/SdSpiCard/SdSpiCard.h
  93. 102 0
      SdFat/src/SdSpiCard/SdSpiESP8266.cpp
  94. 110 0
      SdFat/src/SdSpiCard/SdSpiParticle.cpp
  95. 13 2
      SdFat/src/SdSpiCard/SdSpiSAM3X.cpp
  96. 125 0
      SdFat/src/SdSpiCard/SdSpiSTM32F1.cpp
  97. 21 6
      SdFat/src/SdSpiCard/SdSpiTeensy3.cpp
  98. 12 20
      SdFat/src/SdSpiCard/SoftSPI.h
  99. 37 0
      SdFat/src/SdSpiCard/boards/AvrDevelopersGpioPinMap.h
  100. 37 0
      SdFat/src/SdSpiCard/boards/BobuinoGpioPinMap.h

+ 2 - 32
readme.txt → README.md

@@ -1,32 +1,7 @@
-This is a major rewrite of core FAT code so bugs and compatibility
-problems are likely.  
-
-Please report problems to the email address listed in the 
-"Bugs and Comments" section of the html documentation.
-
-Here are the most recent changes:
-
-Added support for Long File Names. See the LongFileName example.
-
-Replaced the core SdFat code with FatLib, a generic FAT12/FAT16/FAT32
-library.  This may result in bugs and backward compatibility problems.
-
-Added SdFatSoftSpi, a software SPI template class.  See the SoftwareSpi
-example.
-
-Added SdFatLibSpi, a class that uses the Arduino SPI.h library.
-
-Allow simultaneous use of hardware and software SPI with multiple cards.
-See the ThreeCard example. 
- 
-Added the "File" class for compatibility with the Arduino SD.h library 
-
-Added StreamParseInt example to demonstrate the SD.h API.
-
 The Arduino SdFat library provides read/write access to FAT16/FAT32
 The Arduino SdFat library provides read/write access to FAT16/FAT32
 file systems on SD/SDHC flash cards.
 file systems on SD/SDHC flash cards.
 
 
-SdFat requires Arduino 1.05 or greater.
+SdFat requires Arduino 1.6x or greater.
 
 
 To use SdFat, clone the repository or unzip the ZIP file and place the SdFat
 To use SdFat, clone the repository or unzip the ZIP file and place the SdFat
 folder into the libraries sub-folder in your main sketch folder.
 folder into the libraries sub-folder in your main sketch folder.
@@ -45,11 +20,6 @@ html/index.html and read the Main Page.  Next go to the Classes tab and
 read the documentation for the classes SdFat, SdBaseFile, SdFile, File,
 read the documentation for the classes SdFat, SdBaseFile, SdFile, File,
 StdioStream, ifstream, ofstream, and others.
 StdioStream, ifstream, ofstream, and others.
  
  
-Support has been added for Software SPI on AVR, Due, and Teensy 3.1 boards.
-
-See the ThreeCard example for use of multiple SD cards with simultaneous 
-use of hardware and software SPI.
-
 A new class, "File", has been added to provide compatibility with the Arduino
 A new class, "File", has been added to provide compatibility with the Arduino
 SD.h library. To use SdFat with programs written for SD.h replace
 SD.h library. To use SdFat with programs written for SD.h replace
 
 
@@ -62,4 +32,4 @@ SdFat SD;
 
 
 Please continue by reading the html documentation.
 Please continue by reading the html documentation.
 
 
-Updated 21 Mar 2015
+Updated 19 Jul 2016

+ 18 - 16
SdFat/SdFatmainpage.h → SdFat/MainPage/SdFatmainpage.h

@@ -20,7 +20,7 @@
 
 
 /**
 /**
 \mainpage Arduino %SdFat Library
 \mainpage Arduino %SdFat Library
-<CENTER>Copyright &copy; 2012, 2013, 2014, 2015 by William Greiman
+<CENTER>Copyright &copy; 2012, 2013, 2014, 2015, 2016 by William Greiman
 </CENTER>
 </CENTER>
 
 
 \section Intro Introduction
 \section Intro Introduction
@@ -85,7 +85,7 @@ developed to test %SdFat and illustrate its use.
 \section Install Installation
 \section Install Installation
 
 
 You must manually install SdFat by copying the SdFat folder from the download
 You must manually install SdFat by copying the SdFat folder from the download
-package to the Arduino libraries folder in you sketch folder.
+package to the Arduino libraries folder in your sketch folder.
 
 
 See the Manual installation section of this guide.
 See the Manual installation section of this guide.
 
 
@@ -111,12 +111,9 @@ To enable SD card CRC checking set USE_SD_CRC nonzero.
 Set FAT12_SUPPORT nonzero to enable use of FAT12 volumes.
 Set FAT12_SUPPORT nonzero to enable use of FAT12 volumes.
 FAT12 has not been well tested and requires additional flash.
 FAT12 has not been well tested and requires additional flash.
 
 
-Set ENABLE_SPI_TRANSACTION nonzero to enable the SPI transaction feature
+Set ENABLE_SPI_TRANSACTIONS nonzero to enable the SPI transaction feature
 of the standard Arduino SPI library.  You must include SPI.h in your
 of the standard Arduino SPI library.  You must include SPI.h in your
-programs when ENABLE_SPI_TRANSACTION is nonzero.
-
-Set ENABLE_SPI_YIELD nonzero to enable release of the SPI bus during
-SD card busy waits.
+programs when ENABLE_SPI_TRANSACTIONS is nonzero.
 
 
 \section SDPath Paths and Working Directories
 \section SDPath Paths and Working Directories
 
 
@@ -285,11 +282,10 @@ display properly.  Examples this type name are UPPER.low, lower.TXT,
 UPPER.TXT, and lower.txt. 
 UPPER.TXT, and lower.txt. 
 
 
 An application which writes to a file using print(), println() or
 An application which writes to a file using print(), println() or
-\link SdFile::write write() \endlink must close the file or call
-\link SdFile::sync() sync() \endlink at the appropriate time to
+write() must close the file or call sync() at the appropriate time to
 force data and directory information to be written to the SD Card.
 force data and directory information to be written to the SD Card.
 
 
-Applications must use care calling \link SdFile::sync() sync() \endlink
+Applications must use care calling sync() sync()
 since 2048 bytes of I/O is required to update file and
 since 2048 bytes of I/O is required to update file and
 directory information.  This includes writing the current data block, reading
 directory information.  This includes writing the current data block, reading
 the block that contains the directory entry for update, writing the directory
 the block that contains the directory entry for update, writing the directory
@@ -344,11 +340,9 @@ AnalogBinLogger - Fast AVR ADC logger - see the AnalogBinLoggerExtras folder.
 
 
 bench - A read/write benchmark.
 bench - A read/write benchmark.
 
 
-cin_cout - Demo of ArduinoInStream and ArduinoOutStream.
-
 dataLogger - A simple modifiable data logger.
 dataLogger - A simple modifiable data logger.
 
 
-directoryFunctions - Demo of chdir(), ls(), mkdir(), and  rmdir().
+DirectoryFunctions - Demo of chdir(), ls(), mkdir(), and  rmdir().
 
 
 fgets - Demo of the fgets read line/string function.
 fgets - Demo of the fgets read line/string function.
 
 
@@ -368,7 +362,13 @@ QuickStart - A program to quickly test your SD card and SD shield/module.
 
 
 RawWrite - A test of raw write functions for contiguous files.
 RawWrite - A test of raw write functions for contiguous files.
 
 
-readCSV - Read a comma-separated value file using iostream extractors.
+ReadCsv - Function to read a CSV text file one field at a time.
+
+ReadCsvStream - Read a comma-separated value file using iostream extractors.
+
+ReadCsvArray - Read a two dimensional array from a CSV file.
+
+ReadWrite - Compatibility test of Arduino SD ReadWrite example.
 
 
 ReadWriteSdFat - SdFat version of Arduino SD ReadWrite example.
 ReadWriteSdFat - SdFat version of Arduino SD ReadWrite example.
 
 
@@ -382,11 +382,13 @@ SdInfo - Initialize an SD card and analyze its structure for trouble shooting.
 
 
 StdioBench - Demo and test of stdio style stream.
 StdioBench - Demo and test of stdio style stream.
 
 
-StreamParseInt - Demo of the SD.h API and the File class parseInt() function.
-
 ThreeCards - Demonstrate simultaneous use of SdFat, SdFatLibSpi, SdFatSoftSpi.
 ThreeCards - Demonstrate simultaneous use of SdFat, SdFatLibSpi, SdFatSoftSpi.
 
 
 Timestamp - Sets file create, modify, and access timestamps.
 Timestamp - Sets file create, modify, and access timestamps.
 
 
 TwoCards - Example using two SD cards.
 TwoCards - Example using two SD cards.
+
+VolumeFreeSpace - Demonstrate the freeClusterCount() call.
+
+wipe - Example to wipe all data from an already formatted SD.
  */
  */

+ 0 - 67
SdFat/SdFatUtil.h

@@ -1,67 +0,0 @@
-/* Arduino SdFat Library
- * Copyright (C) 2012 by William Greiman
- *
- * This file is part of the Arduino SdFat Library
- *
- * This Library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the Arduino SdFat Library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-#ifndef SdFatUtil_h
-#define SdFatUtil_h
-/**
- * \file
- * \brief Useful utility functions.
- */
-#include "SdFat.h"
-/** Store and print a string in flash memory.*/
-#define PgmPrint(x) SerialPrint_P(PSTR(x))
-/** Store and print a string in flash memory followed by a CR/LF.*/
-#define PgmPrintln(x) SerialPrintln_P(PSTR(x))
-
-namespace SdFatUtil {
-  /** Amount of free RAM
-   * \return The number of free bytes.
-   */
-  int FreeRam();
-  /** %Print a string in flash memory.
-   *
-   * \param[in] pr Print object for output.
-   * \param[in] str Pointer to string stored in flash memory.
-   */
-  void print_P(Print* pr, PGM_P str);
-  /** %Print a string in flash memory followed by a CR/LF.
-   *
-   * \param[in] pr Print object for output.
-   * \param[in] str Pointer to string stored in flash memory.
-   */
-  void println_P(Print* pr, PGM_P str);
-  //----------------------------------------------------------------------------
-  /** %Print a string in flash memory to Serial.
-   *
-   * \param[in] str Pointer to string stored in flash memory.
-   */
-  inline void SerialPrint_P(PGM_P str) {
-    print_P(&Serial, str);
-  }
-  //----------------------------------------------------------------------------
-  /** %Print a string in flash memory to Serial followed by a CR/LF.
-   *
-   * \param[in] str Pointer to string stored in flash memory.
-   */
-  inline void SerialPrintln_P(PGM_P str) {
-    println_P(&Serial, str);
-  }
-}  // namespace SdFatUtil
-using namespace SdFatUtil;  // NOLINT
-#endif  // #define SdFatUtil_h

+ 0 - 171
SdFat/SdSpiSTM32F1.cpp

@@ -1,171 +0,0 @@
-/* Arduino SdSpi Library
- * Copyright (C) 2013 by William Greiman
- *
- * STM32F1 code for Maple and Maple Mini support, 2015 by Victor Perez
- *
- * This file is part of the Arduino SdSpi Library
- *
- * This Library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the Arduino SdSpi Library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-#if defined(__STM32F1__)
-#include "SdSpi.h"
-#include <SPI.h>
-#include <libmaple/dma.h>
-/** Use STM32 DMAC if nonzero */
-#define USE_STM32F1_DMAC 1
-/** Time in ms for DMA receive timeout */
-#define STM32F1_DMA_TIMEOUT 100
-/** DMAC receive channel */
-#define SPI1_DMAC_RX_CH  DMA_CH2
-/** DMAC transmit channel */
-#define SPI1_DMAC_TX_CH  DMA_CH3
-
-volatile bool SPI_DMA_TX_Active = false;
-volatile bool SPI_DMA_RX_Active = false;
-
-/** ISR for DMA TX event. */
-inline void SPI_DMA_TX_Event() {
-  SPI_DMA_TX_Active = false;
-  dma_disable(DMA1, SPI_DMAC_TX_CH);
-}
-
-/** ISR for DMA RX event. */
-inline void SPI_DMA_RX_Event() {
-  SPI_DMA_RX_Active = false;
-  dma_disable(DMA1, SPI1_DMAC_RX_CH);
-}
-//------------------------------------------------------------------------------
-
-/** Disable DMA Channel. */
-static void dmac_channel_disable(dma_channel ul_num) {
-  dma_disable(DMA1, ul_num);
-}
-/** Enable DMA Channel. */
-static void dmac_channel_enable(dma_channel ul_num) {
-  dma_enable(DMA1, ul_num);
-}
-//------------------------------------------------------------------------------
-void SdSpi::begin() {
-  SPI.begin();
-}
-//------------------------------------------------------------------------------
-// start RX DMA
-
-static void spiDmaRX(uint8_t* dst, uint16_t count) {
-//  spi_rx_dma_enable(SPI1);
-  if (count < 1) return;
-  dma_setup_transfer(DMA1, SPI1_DMAC_RX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS,
-                     dst, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT));
-  dma_set_num_transfers(DMA1, SPI1_DMAC_RX_CH, count);  // 2 bytes per pixel
-  SPI_DMA_RX_Active = true;
-  dma_enable(DMA1, SPI1_DMAC_RX_CH);
-}
-//------------------------------------------------------------------------------
-// start TX DMA
-static void spiDmaTX(const uint8_t* src, uint16_t count) {
-  if (count < 1) return;
-  static uint8_t ff = 0XFF;
-
-  if (!src) {
-    src = &ff;
-    dma_setup_transfer(DMA1, SPI1_DMAC_TX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS,
-                       const_cast<uint8_t*>(src), DMA_SIZE_8BITS,
-                      (DMA_FROM_MEM | DMA_TRNS_CMPLT));
-  } else {
-    dma_setup_transfer(DMA1, SPI1_DMAC_TX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS,
-                       const_cast<uint8_t*>(src), DMA_SIZE_8BITS,
-                      (DMA_MINC_MODE  |  DMA_FROM_MEM | DMA_TRNS_CMPLT));
-  }
-  dma_set_num_transfers(DMA1, SPI1_DMAC_TX_CH, count);  // 2 bytes per pixel
-  SPI_DMA_TX_Active = true;
-  dma_enable(DMA1, SPI1_DMAC_TX_CH);
-}
-//------------------------------------------------------------------------------
-//  initialize SPI controller STM32F1
-void SdSpi::init(uint8_t sckDivisor) {
-  if (sckDivisor < SPI_CLOCK_DIV2 || sckDivisor > SPI_CLOCK_DIV256) {
-    sckDivisor = SPI_CLOCK_DIV2;  // may not be needed, testing.
-  }
-  SPI.setClockDivider(sckDivisor);
-  SPI.setBitOrder(MSBFIRST);
-  SPI.setDataMode(SPI_MODE0);
-
-#if USE_STM32F1_DMAC
-  dma_init(DMA1);
-  dma_attach_interrupt(DMA1, SPI1_DMAC_TX_CH, SPI_DMA_TX_Event);
-  dma_attach_interrupt(DMA1, SPI1_DMAC_RX_CH, SPI_DMA_RX_Event);
-  spi_tx_dma_enable(SPI1);
-  spi_rx_dma_enable(SPI1);
-#endif  // USE_STM32F1_DMAC
-}
-//------------------------------------------------------------------------------
-// STM32
-static inline uint8_t spiTransfer(uint8_t b) {
-  return SPI.transfer(b);
-}
-//------------------------------------------------------------------------------
-// should be valid for STM32
-/** SPI receive a byte */
-uint8_t SdSpi::receive() {
-  return spiTransfer(0xFF);
-}
-//------------------------------------------------------------------------------
-/** SPI receive multiple bytes */
-// check and finish.
-
-uint8_t SdSpi::receive(uint8_t* buf, size_t n) {
-  int rtn = 0;
-
-#if USE_STM32F1_DMAC
-
-  spiDmaRX(buf, n);
-  spiDmaTX(0, n);
-
-  uint32_t m = millis();
-  while (SPI_DMA_RX_Active) {
-    if ((millis() - m) > STM32F1_DMA_TIMEOUT)  {
-      dmac_channel_disable(SPI_DMAC_RX_CH);
-      dmac_channel_disable(SPI_DMAC_TX_CH);
-      rtn = 2;
-      break;
-    }
-  }
-
-#else  // USE_STM32F1_DMAC
-  for (size_t i = 0; i < n; i++) {
-    buf[i] = SPI.transfer(0xFF);
-  }
-#endif  // USE_STM32F1_DMAC
-  return rtn;
-}
-//------------------------------------------------------------------------------
-/** SPI send a byte */
-void SdSpi::send(uint8_t b) {
-  spiTransfer(b);
-}
-//------------------------------------------------------------------------------
-void SdSpi::send(const uint8_t* buf , size_t n) {
-#if USE_STM32F1_DMAC
-  spiDmaTX(buf, n);
-  while (SPI_DMA_TX_Active) {}
-
-#else  // #if USE_STM32F1_DMAC
-  SPI.write(buf, n);
-#endif  // #if USE_STM32F1_DMAC
-  // leave RX register empty
-  //  while (spi_is_rx_nonempty(SPI1))
-  uint8_t b = spi_rx_reg(SPI1);
-}
-#endif  // USE_NATIVE_STM32F1_SPI

+ 0 - 71
SdFat/SdVolume.h

@@ -1,71 +0,0 @@
-/* Arduino SdFat Library
- * Copyright (C) 2012 by William Greiman
- *
- * This file is part of the Arduino SdFat Library
- *
- * This Library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This Library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the Arduino SdFat Library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-#ifndef SdVolume_h
-#include "SdSpiCard.h"
-#include "utility/FatLib.h"
-#define SdVolume_h
-#ifndef USE_SD_VOLUME
-#error SdVolume is deperacated.  Remove this line to continue using this class.
-#endif   // USE_SD_VOLUME
-//==============================================================================
-/**
- * \class SdVolume
- * \brief SdVolume Soon to be removed.
- */
-class SdVolume : public FatVolume {
- public:
-  /** Initialize a FAT volume.  Try partition one first then try super
-  * floppy format.
-  *
-  * \param[in] dev The Sd2Card where the volume is located.
-  *
-  * \return true for success else false.
-  */
-  bool init(Sd2Card* dev) {
-    return init(dev, 1) ? true : init(dev, 0);
-  }
-  /** Initialize a FAT volume.
-  *
-  * \param[in] dev The Sd2Card where the volume is located.
-  * \param[in] part the partition to use. Zero for super floppy or 1-4.
-  * \return true for success else false.
-  */
-  bool init(Sd2Card* dev, uint8_t part) {
-    m_sdCard = dev;
-    return FatVolume::init(part);
-  }
-
- private:
-//  friend class FatFile;
-  bool readBlock(uint32_t block, uint8_t* dst) {
-    return m_sdCard->readBlock(block, dst);
-  }
-  bool writeBlock(uint32_t block, const uint8_t* src) {
-    return m_sdCard->writeBlock(block, src);
-  }
-  bool readBlocks(uint32_t block, uint8_t* dst, size_t n) {
-    return m_sdCard->readBlocks(block, dst, n);
-  }
-  bool writeBlocks(uint32_t block, const uint8_t* src, size_t n) {
-    return m_sdCard->writeBlocks(block, src, n);
-  }
-  Sd2Card* m_sdCard;             // Sd2Card object for cache
-};
-#endif  // SdVolume_h

+ 16 - 9
SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino

@@ -1,8 +1,8 @@
 // A simple data logger for the Arduino analog pins with optional DS1307
 // A simple data logger for the Arduino analog pins with optional DS1307
 // uses RTClib from https://github.com/adafruit/RTClib
 // uses RTClib from https://github.com/adafruit/RTClib
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>  // define FreeRam()
+#include "SdFat.h"
+#include "FreeStack.h"
 
 
 #define SD_CHIP_SELECT  SS  // SD chip select pin
 #define SD_CHIP_SELECT  SS  // SD chip select pin
 #define USE_DS1307       0  // set nonzero to use DS1307 RTC
 #define USE_DS1307       0  // set nonzero to use DS1307 RTC
@@ -65,16 +65,23 @@ ostream& operator << (ostream& os, DateTime& dt) {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
-
+  
+  // Wait for USB Serial.
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
   // F() stores strings in flash to save RAM
-  cout << endl << F("FreeRam: ") << FreeRam() << endl;
+  cout << endl << F("FreeStack: ") << FreeStack() << endl;
 
 
 #if WAIT_TO_START
 #if WAIT_TO_START
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
-  while (Serial.read() >= 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
+  // Discard input.
+  do {
+    delay(10);
+  } while(Serial.available() && Serial.read() >= 0);
 #endif  // WAIT_TO_START
 #endif  // WAIT_TO_START
 
 
 #if USE_DS1307
 #if USE_DS1307
@@ -184,5 +191,5 @@ void loop() {
   }
   }
   logfile.close();
   logfile.close();
   cout << F("Done!");
   cout << F("Done!");
-  while (1);
+  SysCall::halt();
 }
 }

+ 10 - 4
SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino

@@ -2,12 +2,12 @@
  * Program to test Short File Name character case flags.
  * Program to test Short File Name character case flags.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 SdFat sd;
 SdFat sd;
 
 
 SdFile file;
 SdFile file;
-char* name[] = {
+const char* name[] = {
   "low.low", "low.Mix", "low.UP",
   "low.low", "low.Mix", "low.UP",
   "Mix.low", "Mix.Mix", "Mix.UP",
   "Mix.low", "Mix.Mix", "Mix.UP",
   "UP.low",  "UP.Mix",  "UP.UP"
   "UP.low",  "UP.Mix",  "UP.UP"
@@ -15,9 +15,15 @@ char* name[] = {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   Serial.println("type any character to start");
   Serial.println("type any character to start");
-  while (Serial.read() < 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   if (!sd.begin()) {
   if (!sd.begin()) {
     Serial.println("begin failed");
     Serial.println("begin failed");
     return;
     return;

+ 5 - 2
SdFat/examples/#attic/HelloWorld/HelloWorld.ino

@@ -1,5 +1,5 @@
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 //  create a serial output stream
 //  create a serial output stream
 ArduinoOutStream cout(Serial);
 ArduinoOutStream cout(Serial);
@@ -7,7 +7,10 @@ ArduinoOutStream cout(Serial);
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
 
 
-  while (!Serial) {}  // wait for Leonardo
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(2000);
   delay(2000);
 
 
   cout << "Hello, World!\n";
   cout << "Hello, World!\n";

+ 4 - 4
SdFat/examples/#attic/MiniSerial/MiniSerial.ino

@@ -5,16 +5,16 @@
 // Will not work on Due, Leonardo, or Teensy
 // Will not work on Due, Leonardo, or Teensy
 
 
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 #ifdef UDR0  // Must be AVR with serial port zero.
 #ifdef UDR0  // Must be AVR with serial port zero.
-#include <MinimumSerial.h>
+#include "MinimumSerial.h"
 
 
 MinimumSerial MiniSerial;
 MinimumSerial MiniSerial;
 
 
 void setup() {
 void setup() {
   MiniSerial.begin(9600);
   MiniSerial.begin(9600);
-  MiniSerial.println(FreeRam());
+  MiniSerial.println(FreeStack());
 }
 }
 void loop() {
 void loop() {
   int c;
   int c;

+ 15 - 11
SdFat/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino

@@ -15,15 +15,19 @@ const uint16_t N_PRINT = 20000;
 File file;
 File file;
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-void error(char* s) {
+void error(const char* s) {
   Serial.println(s);
   Serial.println(s);
-  while(1);
+  while (1) {
+    yield();
+  }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
+  
+  // Wait for USB Serial 
   while (!Serial) {
   while (!Serial) {
-    // wait for Leonardo
+    yield();
   }
   }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -32,22 +36,22 @@ void loop() {
   uint32_t minLatency;
   uint32_t minLatency;
   uint32_t totalLatency;
   uint32_t totalLatency;
 
 
-  while (Serial.read() >= 0) {
-  }
+  // Read any existing Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
+
   // F() stores strings in flash to save RAM
   // F() stores strings in flash to save RAM
   Serial.println(F("Type any character to start"));
   Serial.println(F("Type any character to start"));
-  while (Serial.read() <= 0) {
+  while (!Serial.available()) {
+    yield();
   }
   }
-  delay(400);  // catch Due reset problem
-
 
 
   // initialize the SD card
   // initialize the SD card
-
   if (!SD.begin(chipSelect)) {
   if (!SD.begin(chipSelect)) {
     error("begin");
     error("begin");
   }
   }
-
-
+  
   Serial.println(F("Starting print test.  Please wait.\n"));
   Serial.println(F("Starting print test.  Please wait.\n"));
 
 
   // do write test
   // do write test

+ 5 - 1
SdFat/examples/#attic/SD_Size/SD_Size.ino

@@ -9,7 +9,11 @@ File file;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    yield();
+  }
 
 
   if (!SD.begin()) {
   if (!SD.begin()) {
     Serial.println("begin failed");
     Serial.println("begin failed");

+ 7 - 3
SdFat/examples/#attic/SdFatSize/SdFatSize.ino

@@ -4,7 +4,7 @@
  *
  *
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 SdFat sd;
 SdFat sd;
 
 
@@ -12,8 +12,12 @@ SdFile file;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  
   if (!sd.begin()) {
   if (!sd.begin()) {
     Serial.println("begin failed");
     Serial.println("begin failed");
     return;
     return;

+ 7 - 4
SdFat/examples/StreamParseInt/StreamParseInt.ino → SdFat/examples/#attic/StreamParseInt/StreamParseInt.ino

@@ -1,7 +1,7 @@
 // Simple demo of the Stream parsInt() member function.
 // Simple demo of the Stream parsInt() member function.
 #include <SPI.h>
 #include <SPI.h>
 // The next two lines replace #include <SD.h>.
 // The next two lines replace #include <SD.h>.
-#include <SdFat.h>
+#include "SdFat.h"
 SdFat SD;
 SdFat SD;
 
 
 // SD card chip select pin - Modify the value of csPin for your SD module.
 // SD card chip select pin - Modify the value of csPin for your SD module.
@@ -12,10 +12,13 @@ File file;
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
   // Wait for USB Serial.
   // Wait for USB Serial.
-  while(!Serial) {}
+  while(!Serial) {
+    SysCall::yield();
+  }
   Serial.println(F("Type any character to start"));
   Serial.println(F("Type any character to start"));
-  while (!Serial.available()) {}
-
+  while (!Serial.available()) {
+    SysCall::yield(); 
+  }
   // Initialize the SD.
   // Initialize the SD.
   if (!SD.begin(csPin)) {
   if (!SD.begin(csPin)) {
     Serial.println(F("begin error"));
     Serial.println(F("begin error"));

+ 9 - 5
SdFat/examples/#attic/append/append.ino

@@ -6,7 +6,7 @@
  * The program will open and close the file 100 times.
  * The program will open and close the file 100 times.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -25,12 +25,16 @@ void setup() {
   char name[] = "append.txt";
   char name[] = "append.txt";
 
 
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
   // F() stores strings in flash to save RAM
   cout << endl << F("Type any character to start\n");
   cout << endl << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // Catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.

+ 9 - 5
SdFat/examples/#attic/average/average.ino

@@ -2,7 +2,7 @@
  * Calculate the sum and average of a list of floating point numbers
  * Calculate the sum and average of a list of floating point numbers
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -54,12 +54,16 @@ void calcAverage() {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
   // F() stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // Catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.

+ 17 - 8
SdFat/examples/#attic/benchSD/benchSD.ino

@@ -18,14 +18,20 @@ uint8_t buf[BUF_SIZE];
 File file;
 File file;
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-void error(char* s) {
+void error(const char* s) {
   Serial.println(s);
   Serial.println(s);
-  while(1);
+  while (1) {
+    yield();
+  }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    yield();
+  }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void loop() {
 void loop() {
@@ -33,14 +39,17 @@ void loop() {
   uint32_t minLatency;
   uint32_t minLatency;
   uint32_t totalLatency;
   uint32_t totalLatency;
 
 
-  // discard any input
-  while (Serial.read() >= 0) {}
+  // Discard any input.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
   // F() stores strings in flash to save RAM
   // F() stores strings in flash to save RAM
   Serial.println(F("Type any character to start"));
   Serial.println(F("Type any character to start"));
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
-
+  
+  while (!Serial.available()) {
+    yield();
+  }
   if (!SD.begin(chipSelect)) {
   if (!SD.begin(chipSelect)) {
     error("begin");
     error("begin");
   }
   }

+ 6 - 2
SdFat/examples/#attic/bufstream/bufstream.ino

@@ -2,7 +2,7 @@
  * Use of ibufsteam to parse a line and obufstream to format a line
  * Use of ibufsteam to parse a line and obufstream to format a line
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // create a serial output stream
 // create a serial output stream
 ArduinoOutStream cout(Serial);
 ArduinoOutStream cout(Serial);
@@ -12,7 +12,11 @@ void setup() {
   int i, j, k;    // values from parsed line
   int i, j, k;    // values from parsed line
 
 
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(2000);
   delay(2000);
 
 
   // initialize input string
   // initialize input string

+ 6 - 3
SdFat/examples/cin_cout/cin_cout.ino → SdFat/examples/#attic/cin_cout/cin_cout.ino

@@ -2,7 +2,7 @@
  * Demo of ArduinoInStream and ArduinoOutStream
  * Demo of ArduinoInStream and ArduinoOutStream
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // create serial output stream
 // create serial output stream
 ArduinoOutStream cout(Serial);
 ArduinoOutStream cout(Serial);
@@ -15,11 +15,14 @@ ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void loop() {
 void loop() {
-  int32_t n;
+  int32_t n = 0;
 
 
   cout << "\nenter an integer\n";
   cout << "\nenter an integer\n";
 
 

+ 8 - 4
SdFat/examples/#attic/eventlog/eventlog.ino

@@ -2,7 +2,7 @@
  * Append a line to a file - demo of pathnames and streams
  * Append a line to a file - demo of pathnames and streams
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -36,11 +36,15 @@ void logEvent(const char *msg) {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
   // F() stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   delay(400);  // catch Due reset problem
   delay(400);  // catch Due reset problem
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with

+ 11 - 7
SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino

@@ -1,6 +1,6 @@
 // Demo of rewriting a line read by fgets
 // Demo of rewriting a line read by fgets
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD card chip select pin
 // SD card chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -83,13 +83,17 @@ void makeTestFile() {
   wrfile.close();
   wrfile.close();
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-void setup(void) {
+void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.
@@ -103,4 +107,4 @@ void setup(void) {
 
 
   cout << F("\nDone\n");
   cout << F("\nDone\n");
 }
 }
-void loop(void) {}
+void loop() {}

+ 6 - 3
SdFat/examples/#attic/readlog/readlog.ino

@@ -3,7 +3,7 @@
  * Demo of pathnames and working directories
  * Demo of pathnames and working directories
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -17,8 +17,11 @@ ArduinoOutStream cout(Serial);
 void setup() {
 void setup() {
   int c;
   int c;
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.
   if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
   if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {

+ 7 - 1
SdFat/examples/#attic/readme.txt

@@ -7,9 +7,13 @@ append - This sketch creates a large file by successive
 
 
 average - A demonstration of parsing floating point numbers.
 average - A demonstration of parsing floating point numbers.
 
 
+BaseExtCaseTest - Long file name test.
+
 benchSD - A read/write benchmark for the standard Arduino SD.h library.
 benchSD - A read/write benchmark for the standard Arduino SD.h library.
 
 
-bufstream - ibufsteam to parse a line and obufstream to format a line.             
+bufstream - ibufsteam to parse a line and obufstream to format a line.
+
+cin_cout - Demo of ArduinoInStream and ArduinoOutStream.             
 
 
 eventlog - Append a line to a file - demo of pathnames and streams.
 eventlog - Append a line to a file - demo of pathnames and streams.
 
 
@@ -26,3 +30,5 @@ readlog - Read file. Demo of pathnames and current working directory.
 SD_Size - Determine flash used by SD.h example.
 SD_Size - Determine flash used by SD.h example.
 
 
 SdFatSize - Determine flash used by SdFat.
 SdFatSize - Determine flash used by SdFat.
+
+StreamParseInt - Simple demo of the Stream parsInt() member function.

+ 16 - 14
SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino

@@ -21,8 +21,8 @@
  */
  */
 #ifdef __AVR__
 #ifdef __AVR__
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 #include "AnalogBinLogger.h"
 #include "AnalogBinLogger.h"
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // Analog pin number list for a sample.  Pins may be in any order and pin
 // Analog pin number list for a sample.  Pins may be in any order and pin
@@ -136,7 +136,7 @@ const uint8_t PIN_COUNT = sizeof(PIN_LIST)/sizeof(PIN_LIST[0]);
 const uint16_t MIN_ADC_CYCLES = 15;
 const uint16_t MIN_ADC_CYCLES = 15;
 
 
 // Extra cpu cycles to setup ADC with more than one pin per sample.
 // Extra cpu cycles to setup ADC with more than one pin per sample.
-const uint16_t ISR_SETUP_ADC = 100;
+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, millis, micros.
 const uint16_t ISR_TIMER0 = 160;
 const uint16_t ISR_TIMER0 = 160;
@@ -294,8 +294,7 @@ void adcInit(metadata_t* meta) {
   adps = ADC_PRESCALER;
   adps = ADC_PRESCALER;
 #else  // ADC_PRESCALER
 #else  // ADC_PRESCALER
   // Allow extra cpu cycles to change ADC settings if more than one pin.
   // Allow extra cpu cycles to change ADC settings if more than one pin.
-  int32_t adcCycles = (ticks - ISR_TIMER0)/PIN_COUNT;
-  - (PIN_COUNT > 1 ? ISR_SETUP_ADC : 0);
+  int32_t adcCycles = (ticks - ISR_TIMER0)/PIN_COUNT - ISR_SETUP_ADC;
 
 
   for (adps = 7; adps > 0; adps--) {
   for (adps = 7; adps > 0; adps--) {
     if (adcCycles >= (MIN_ADC_CYCLES << adps)) {
     if (adcCycles >= (MIN_ADC_CYCLES << adps)) {
@@ -385,7 +384,7 @@ void adcInit(metadata_t* meta) {
   meta->cpuFrequency = F_CPU;
   meta->cpuFrequency = F_CPU;
   float sampleRate = (float)meta->cpuFrequency/meta->sampleInterval;
   float sampleRate = (float)meta->cpuFrequency/meta->sampleInterval;
   Serial.print(F("Sample pins:"));
   Serial.print(F("Sample pins:"));
-  for (int i = 0; i < meta->pinCount; i++) {
+  for (uint8_t i = 0; i < meta->pinCount; i++) {
     Serial.print(' ');
     Serial.print(' ');
     Serial.print(meta->pinNumber[i], DEC);
     Serial.print(meta->pinNumber[i], DEC);
   }
   }
@@ -471,7 +470,6 @@ void binaryToCsv() {
   csvStream.println();
   csvStream.println();
   uint32_t tPct = millis();
   uint32_t tPct = millis();
   while (!Serial.available() && binFile.read(&buf, 512) == 512) {
   while (!Serial.available() && binFile.read(&buf, 512) == 512) {
-    uint16_t i;
     if (buf.count == 0) {
     if (buf.count == 0) {
       break;
       break;
     }
     }
@@ -782,8 +780,8 @@ void setup(void) {
   // Read the first sample pin to init the ADC.
   // Read the first sample pin to init the ADC.
   analogRead(PIN_LIST[0]);
   analogRead(PIN_LIST[0]);
 
 
-  Serial.print(F("FreeRam: "));
-  Serial.println(FreeRam());
+  Serial.print(F("FreeStack: "));
+  Serial.println(FreeStack());
 
 
   // initialize file system.
   // initialize file system.
   if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
   if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
@@ -793,8 +791,10 @@ void setup(void) {
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void loop(void) {
 void loop(void) {
-  // discard any input
-  while (Serial.read() >= 0) {}
+  // Read any Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
   Serial.println();
   Serial.println();
   Serial.println(F("type:"));
   Serial.println(F("type:"));
   Serial.println(F("c - convert file to csv"));
   Serial.println(F("c - convert file to csv"));
@@ -802,15 +802,17 @@ void loop(void) {
   Serial.println(F("e - overrun error details"));
   Serial.println(F("e - overrun error details"));
   Serial.println(F("r - record ADC data"));
   Serial.println(F("r - record ADC data"));
 
 
-  while(!Serial.available()) {}
+  while(!Serial.available()) {
+    SysCall::yield();
+  }
   char c = tolower(Serial.read());
   char c = tolower(Serial.read());
   if (ERROR_LED_PIN >= 0) {
   if (ERROR_LED_PIN >= 0) {
     digitalWrite(ERROR_LED_PIN, LOW);
     digitalWrite(ERROR_LED_PIN, LOW);
   }
   }
-  // Read any extra Serial data.
+  // Read any Serial data.
   do {
   do {
     delay(10);
     delay(10);
-  } while (Serial.read() >= 0);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
   if (c == 'c') {
   if (c == 'c') {
     binaryToCsv();
     binaryToCsv();

+ 18 - 12
SdFat/examples/LongFileName/LongFileName.ino

@@ -2,8 +2,8 @@
 // You can use test files located in
 // You can use test files located in
 // SdFat/examples/LongFileName/testFiles.
 // SdFat/examples/LongFileName/testFiles.
 #include<SPI.h>
 #include<SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 
 // SD card chip select pin.
 // SD card chip select pin.
 const uint8_t SD_CS_PIN = SS;
 const uint8_t SD_CS_PIN = SS;
@@ -34,8 +34,8 @@ void setup() {
   if (!sd.begin(SD_CS_PIN)) {
   if (!sd.begin(SD_CS_PIN)) {
     sd.initErrorHalt();
     sd.initErrorHalt();
   }
   }
-  Serial.print(F("Free RAM: "));
-  Serial.println(FreeRam());
+  Serial.print(F("FreeStack: "));
+  Serial.println(FreeStack());
   Serial.println();
   Serial.println();
 
 
   // List files in root directory.
   // List files in root directory.
@@ -63,25 +63,31 @@ void setup() {
 void loop() {
 void loop() {
   int c;
   int c;
 
 
-  // Discard any Serial input.
-  while (Serial.read() > 0) {}
+  // Read any existing Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
   Serial.print(F("\r\nEnter File Number: "));
   Serial.print(F("\r\nEnter File Number: "));
 
 
-  while ((c = Serial.read()) < 0) {};
-  if (!isdigit(c) || (c -= '0') >= n) {
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
+  c = Serial.read();
+  uint8_t i = c - '0';
+  if (!isdigit(c) || i >= n) {
     Serial.println(F("Invald number"));
     Serial.println(F("Invald number"));
     return;
     return;
   }
   }
-  Serial.println(c);
-  if (!file.open(&dirFile, dirIndex[c], O_READ)) {
+  Serial.println(i);
+  if (!file.open(&dirFile, dirIndex[i], O_READ)) {
     sd.errorHalt(F("open"));
     sd.errorHalt(F("open"));
   }
   }
   Serial.println();
   Serial.println();
 
 
-  char last;
+  char last = 0;
 
 
   // Copy up to 500 characters to Serial.
   // Copy up to 500 characters to Serial.
-  for (int i = 0; i < 500 && (c = file.read()) > 0; i++)  {
+  for (int k = 0; k < 500 && (c = file.read()) > 0; k++)  {
     Serial.write(last = (char)c);
     Serial.write(last = (char)c);
   }
   }
   // Add new line if missing from last line.
   // Add new line if missing from last line.

+ 53 - 22
SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino

@@ -14,11 +14,18 @@
  * Data is written to the file using a SD multiple block write command.
  * Data is written to the file using a SD multiple block write command.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
+#include "UserDataType.h"  // Edit this include file to change data_t.
+//------------------------------------------------------------------------------
+// Set useSharedSpi true for use of an SPI sensor.
+// May not work for some cards.
+const bool useSharedSpi = false;
+
+// File start time in micros.
+uint32_t startMicros;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // User data functions.  Modify these functions for your data items.
 // User data functions.  Modify these functions for your data items.
-#include "UserDataType.h"  // Edit this include file to change data_t.
 
 
 // Acquire a data record.
 // Acquire a data record.
 void acquireData(data_t* data) {
 void acquireData(data_t* data) {
@@ -30,7 +37,7 @@ void acquireData(data_t* data) {
 
 
 // Print a data record.
 // Print a data record.
 void printData(Print* pr, data_t* data) {
 void printData(Print* pr, data_t* data) {
-  pr->print(data->time);
+  pr->print(data->time - startMicros);
   for (int i = 0; i < ADC_DIM; i++) {
   for (int i = 0; i < ADC_DIM; i++) {
     pr->write(',');
     pr->write(',');
     pr->print(data->adc[i]);
     pr->print(data->adc[i]);
@@ -61,6 +68,7 @@ const uint8_t SD_CS_PIN = SS;
 // Digital pin to indicate an error, set to -1 if not used.
 // Digital pin to indicate an error, set to -1 if not used.
 // The led blinks for fatal errors. The led goes on solid for SD write
 // The led blinks for fatal errors. The led goes on solid for SD write
 // overrun errors and logging continues.
 // overrun errors and logging continues.
+#undef ERROR_LED_PIN
 const int8_t ERROR_LED_PIN = -1;
 const int8_t ERROR_LED_PIN = -1;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // File definitions.
 // File definitions.
@@ -381,18 +389,21 @@ void logData() {
   // Wait for Serial Idle.
   // Wait for Serial Idle.
   Serial.flush();
   Serial.flush();
   delay(10);
   delay(10);
+  bool closeFile = false;
   uint32_t bn = 0;
   uint32_t bn = 0;
   uint32_t t0 = millis();
   uint32_t t0 = millis();
   uint32_t t1 = t0;
   uint32_t t1 = t0;
   uint32_t overrun = 0;
   uint32_t overrun = 0;
   uint32_t overrunTotal = 0;
   uint32_t overrunTotal = 0;
   uint32_t count = 0;
   uint32_t count = 0;
+  uint32_t maxDelta = 0;
+  uint32_t minDelta = 99999;
   uint32_t maxLatency = 0;
   uint32_t maxLatency = 0;
-  int32_t diff;
-  // Start at a multiple of interval.
-  uint32_t logTime = micros()/LOG_INTERVAL_USEC + 1;
-  logTime *= LOG_INTERVAL_USEC;
-  bool closeFile = false;
+  uint32_t logTime = micros();
+
+  // Set time for first record of file.
+  startMicros = logTime + LOG_INTERVAL_USEC;
+
   while (1) {
   while (1) {
     // Time for next data record.
     // Time for next data record.
     logTime += LOG_INTERVAL_USEC;
     logTime += LOG_INTERVAL_USEC;
@@ -401,7 +412,7 @@ void logData() {
     }
     }
 
 
     if (closeFile) {
     if (closeFile) {
-      if (curBlock != 0 && curBlock->count >= 0) {
+      if (curBlock != 0) {
         // Put buffer in full queue.
         // Put buffer in full queue.
         fullQueue[fullHead] = curBlock;
         fullQueue[fullHead] = curBlock;
         fullHead = queueNext(fullHead);
         fullHead = queueNext(fullHead);
@@ -415,21 +426,30 @@ void logData() {
         curBlock->overrun = overrun;
         curBlock->overrun = overrun;
         overrun = 0;
         overrun = 0;
       }
       }
-      do {
-        diff = logTime - micros();
-      } while(diff > 0);
-      if (diff < -10) {
-        error("LOG_INTERVAL_USEC too small");
+      if ((int32_t)(logTime - micros()) < 0) {
+        error("Rate too fast");             
       }
       }
+      int32_t delta;
+      do {
+        delta = micros() - logTime;
+      } while (delta < 0);
       if (curBlock == 0) {
       if (curBlock == 0) {
         overrun++;
         overrun++;
       } else {
       } else {
+        if (useSharedSpi) {
+          sd.card()->chipSelectHigh();
+        }
         acquireData(&curBlock->data[curBlock->count++]);
         acquireData(&curBlock->data[curBlock->count++]);
+        if (useSharedSpi) {
+          sd.card()->chipSelectLow();
+        }        
         if (curBlock->count == DATA_DIM) {
         if (curBlock->count == DATA_DIM) {
           fullQueue[fullHead] = curBlock;
           fullQueue[fullHead] = curBlock;
           fullHead = queueNext(fullHead);
           fullHead = queueNext(fullHead);
           curBlock = 0;
           curBlock = 0;
         }
         }
+        if ((uint32_t)delta > maxDelta) maxDelta = delta;
+        if ((uint32_t)delta < minDelta) minDelta = delta;          
       }
       }
     }
     }
 
 
@@ -490,6 +510,9 @@ void logData() {
   Serial.println(maxLatency);
   Serial.println(maxLatency);
   Serial.print(F("Record time sec: "));
   Serial.print(F("Record time sec: "));
   Serial.println(0.001*(t1 - t0), 3);
   Serial.println(0.001*(t1 - t0), 3);
+  Serial.print(minDelta);
+  Serial.print(F(" <= jitter microseconds <= "));
+  Serial.println(maxDelta);  
   Serial.print(F("Sample count: "));
   Serial.print(F("Sample count: "));
   Serial.println(count);
   Serial.println(count);
   Serial.print(F("Samples/sec: "));
   Serial.print(F("Samples/sec: "));
@@ -504,10 +527,14 @@ void setup(void) {
     pinMode(ERROR_LED_PIN, OUTPUT);
     pinMode(ERROR_LED_PIN, OUTPUT);
   }
   }
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 
 
-  Serial.print(F("FreeRam: "));
-  Serial.println(FreeRam());
+  Serial.print(F("FreeStack: "));
+  Serial.println(FreeStack());
   Serial.print(F("Records/block: "));
   Serial.print(F("Records/block: "));
   Serial.println(DATA_DIM);
   Serial.println(DATA_DIM);
   if (sizeof(block_t) != 512) {
   if (sizeof(block_t) != 512) {
@@ -521,8 +548,10 @@ void setup(void) {
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void loop(void) {
 void loop(void) {
-  // discard any input
-  while (Serial.read() >= 0) {}
+  // Read any Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
   Serial.println();
   Serial.println();
   Serial.println(F("type:"));
   Serial.println(F("type:"));
   Serial.println(F("c - convert file to csv"));
   Serial.println(F("c - convert file to csv"));
@@ -530,13 +559,15 @@ void loop(void) {
   Serial.println(F("e - overrun error details"));
   Serial.println(F("e - overrun error details"));
   Serial.println(F("r - record data"));
   Serial.println(F("r - record data"));
 
 
-  while(!Serial.available()) {}
+  while(!Serial.available()) {
+    SysCall::yield();
+  }
   char c = tolower(Serial.read());
   char c = tolower(Serial.read());
 
 
   // Discard extra Serial data.
   // Discard extra Serial data.
   do {
   do {
     delay(10);
     delay(10);
-  } while (Serial.read() >= 0);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
   if (ERROR_LED_PIN >= 0) {
   if (ERROR_LED_PIN >= 0) {
     digitalWrite(ERROR_LED_PIN, LOW);
     digitalWrite(ERROR_LED_PIN, LOW);

+ 16 - 6
SdFat/examples/OpenNext/OpenNext.ino

@@ -2,9 +2,9 @@
  * Print size, modify date/time, and name for all files in root.
  * Print size, modify date/time, and name for all files in root.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
-// SD chip select pin
+// SD default chip select pin.
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
 
 
 // file system object
 // file system object
@@ -14,9 +14,16 @@ SdFile file;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
-  delay(1000);
-  Serial.println();
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  
+  Serial.println("Type any character to start");
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.
@@ -24,7 +31,10 @@ void setup() {
     sd.initErrorHalt();
     sd.initErrorHalt();
   }
   }
 
 
-  // open next file in root.  The volume working directory, vwd, is root
+  // Open next file in root.  The volume working directory, vwd, is root.
+  // Warning, openNext starts at the current position of sd.vwd() so a
+  // rewind may be neccessary in your application.
+  sd.vwd()->rewind();
   while (file.openNext(sd.vwd(), O_READ)) {
   while (file.openNext(sd.vwd(), O_READ)) {
     file.printFileSize(&Serial);
     file.printFileSize(&Serial);
     Serial.write(' ');
     Serial.write(' ');

+ 12 - 8
SdFat/examples/PrintBenchmark/PrintBenchmark.ino

@@ -2,8 +2,8 @@
  * This program is a simple Print benchmark.
  * This program is a simple Print benchmark.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -25,8 +25,9 @@ ArduinoOutStream cout(Serial);
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
+  // Wait for USB Serial 
   while (!Serial) {
   while (!Serial) {
-    // wait for Leonardo
+    SysCall::yield();
   }
   }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -35,15 +36,18 @@ void loop() {
   uint32_t minLatency;
   uint32_t minLatency;
   uint32_t totalLatency;
   uint32_t totalLatency;
 
 
-  while (Serial.read() >= 0) {
-  }
-  // pstr stores strings in flash to save RAM
+  // Read any existing Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
+  // F stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {
+  while (!Serial.available()) {
+    SysCall::yield();
   }
   }
   delay(400);  // catch Due reset problem
   delay(400);  // catch Due reset problem
 
 
-  cout << F("Free RAM: ") << FreeRam() << endl;
+  cout << F("FreeStack: ") << FreeStack() << endl;
 
 
   // initialize the SD card at SPI_FULL_SPEED for best performance.
   // initialize the SD card at SPI_FULL_SPEED for best performance.
   // try SPI_HALF_SPEED if bus errors occur.
   // try SPI_HALF_SPEED if bus errors occur.

+ 20 - 11
SdFat/examples/QuickStart/QuickStart.ino

@@ -1,7 +1,7 @@
 // Quick hardware test.
 // Quick hardware test.
 //
 //
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 //
 //
 // Set DISABLE_CHIP_SELECT to disable a second SPI device.
 // Set DISABLE_CHIP_SELECT to disable a second SPI device.
 // For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
 // For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
@@ -39,8 +39,11 @@ void reformatMsg() {
 
 
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // Wait for Leonardo.
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   cout << F("\nSPI pins:\n");
   cout << F("\nSPI pins:\n");
   cout << F("MISO: ") << int(MISO) << endl;
   cout << F("MISO: ") << int(MISO) << endl;
   cout << F("MOSI: ") << int(MOSI) << endl;
   cout << F("MOSI: ") << int(MOSI) << endl;
@@ -64,8 +67,10 @@ void setup() {
 
 
 bool firstTry = true;
 bool firstTry = true;
 void loop() {
 void loop() {
-  // read any existing Serial data
-  while (Serial.read() >= 0) {}
+  // Read any existing Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
   if (!firstTry) {
   if (!firstTry) {
     cout << F("\nRestarting\n");
     cout << F("\nRestarting\n");
@@ -73,9 +78,9 @@ void loop() {
   firstTry = false;
   firstTry = false;
 
 
   cout << F("\nEnter the chip select pin number: ");
   cout << F("\nEnter the chip select pin number: ");
-  while (!Serial.available()) {}
-  delay(400);  // catch Due restart problem
-
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   cin.readline();
   cin.readline();
   if (cin >> chipSelect) {
   if (cin >> chipSelect) {
     cout << chipSelect << endl;
     cout << chipSelect << endl;
@@ -150,8 +155,12 @@ void loop() {
     reformatMsg();
     reformatMsg();
     return;
     return;
   }
   }
-  // read any existing Serial data
-  while (Serial.read() >= 0) {}
+  // Read any extra Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
   cout << F("\nSuccess!  Type any character to restart.\n");
   cout << F("\nSuccess!  Type any character to restart.\n");
-  while (Serial.read() < 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 }
 }

+ 70 - 64
SdFat/examples/RawWrite/RawWrite.ino

@@ -3,11 +3,7 @@
  * can be used for high speed data logging.
  * can be used for high speed data logging.
  *
  *
  * This program simulates logging from a source that produces
  * This program simulates logging from a source that produces
- * data at a constant rate of one block every MICROS_PER_BLOCK.
- *
- * If a high quality SanDisk card is used with this program
- * no overruns occur and the maximum block write time is
- * under 2000 micros.
+ * data at a constant rate of RATE_KB_PER_SEC.
  *
  *
  * Note: Apps should create a very large file then truncates it
  * Note: Apps should create a very large file then truncates it
  * to the length that is used for a logging. It only takes
  * to the length that is used for a logging. It only takes
@@ -15,17 +11,21 @@
  * marks the blocks as erased; no data transfer is required.
  * marks the blocks as erased; no data transfer is required.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
 
 
-// number of blocks in the contiguous file
-const uint32_t BLOCK_COUNT = 10000UL;
+const uint32_t RATE_KB_PER_SEC = 100;
+
+const uint32_t TEST_TIME_SEC = 100;
 
 
-// time to produce a block of data
-const uint32_t MICROS_PER_BLOCK = 10000;
+// Time between printing progress dots
+const uint32_t DOT_TIME_MS = 5000UL;
+
+// number of blocks in the contiguous file
+const uint32_t BLOCK_COUNT = (1000*RATE_KB_PER_SEC*TEST_TIME_SEC + 511)/512;
 
 
 // file system
 // file system
 SdFat sd;
 SdFat sd;
@@ -42,26 +42,27 @@ ArduinoOutStream cout(Serial);
 // store error strings in flash to save RAM
 // store error strings in flash to save RAM
 #define error(s) sd.errorHalt(F(s))
 #define error(s) sd.errorHalt(F(s))
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-// log of first overruns
-#define OVER_DIM 20
-struct {
-  uint32_t block;
-  uint32_t micros;
-} over[OVER_DIM];
-//------------------------------------------------------------------------------
 void setup(void) {
 void setup(void) {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void loop(void) {
 void loop(void) {
-  while (Serial.read() >= 0) {}
-  // pstr stores strings in flash to save RAM
+  // Read any extra Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
+  // F stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
-  cout << F("Free RAM: ") << FreeRam() << endl;
+  cout << F("FreeStack: ") << FreeStack() << endl;
 
 
   // initialize the SD card at SPI_FULL_SPEED for best performance.
   // initialize the SD card at SPI_FULL_SPEED for best performance.
   // try SPI_HALF_SPEED if bus errors occur.
   // try SPI_HALF_SPEED if bus errors occur.
@@ -96,28 +97,48 @@ void loop(void) {
     pCache[i + 63] = '\n';
     pCache[i + 63] = '\n';
   }
   }
 
 
-  cout << F("Start raw write of ") << file.fileSize() << F(" bytes at\n");
-  cout << 512000000UL/MICROS_PER_BLOCK << F(" bytes per second\n");
-  cout << F("Please wait ") << (BLOCK_COUNT*MICROS_PER_BLOCK)/1000000UL;
-  cout << F(" seconds\n");
-
+  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
   // tell card to setup for multiple block write with pre-erase
   if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
   if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
     error("writeStart failed");
     error("writeStart failed");
   }
   }
   // init stats
   // init stats
-  uint16_t overruns = 0;
+
+  delay(1000);
+  uint32_t dotCount = 0;
+  uint32_t maxQueuePrint = 0;
   uint32_t maxWriteTime = 0;
   uint32_t maxWriteTime = 0;
-  uint32_t t = micros();
-  uint32_t tNext = t;
+  uint32_t minWriteTime = 9999999;
+  uint32_t totalWriteTime = 0;
+  uint32_t maxQueueSize = 0;
+  uint32_t nWrite = 0;
+  uint32_t b = 0;
 
 
   // write data
   // write data
-  for (uint32_t b = 0; b < BLOCK_COUNT; b++) {
-    // write must be done by this time
-    tNext += MICROS_PER_BLOCK;
-
+    uint32_t startTime = millis();
+  while (nWrite < BLOCK_COUNT) {
+    uint32_t nProduced = RATE_KB_PER_SEC*(millis() - startTime)/512UL;
+    uint32_t queueSize = nProduced - nWrite;
+    if (queueSize == 0) continue;
+    if (queueSize > maxQueueSize) {
+      maxQueueSize = queueSize;
+    }
+    if ((millis() - startTime - dotCount*DOT_TIME_MS) > DOT_TIME_MS) {
+      if (maxQueueSize != maxQueuePrint) {
+        cout << F("\nQ: ") << maxQueueSize << endl;
+        maxQueuePrint = maxQueueSize;
+      } else {
+        cout << ".";
+        if (++dotCount%10 == 0) {
+          cout << endl;
+        }
+      }
+    }
     // put block number at start of first line in block
     // put block number at start of first line in block
-    uint32_t n = b;
+    uint32_t n = b++;
     for (int8_t d = 5; d >= 0; d--) {
     for (int8_t d = 5; d >= 0; d--) {
       pCache[d] = n || d == 5 ? n % 10 + '0' : ' ';
       pCache[d] = n || d == 5 ? n % 10 + '0' : ' ';
       n /= 10;
       n /= 10;
@@ -128,45 +149,30 @@ void loop(void) {
       error("writeData failed");
       error("writeData failed");
     }
     }
     tw = micros() - tw;
     tw = micros() - tw;
-
+    totalWriteTime += tw;
     // check for max write time
     // check for max write time
     if (tw > maxWriteTime) {
     if (tw > maxWriteTime) {
       maxWriteTime = tw;
       maxWriteTime = tw;
     }
     }
-    // check for overrun
-    if (micros() > tNext) {
-      if (overruns < OVER_DIM) {
-        over[overruns].block = b;
-        over[overruns].micros = tw;
-      }
-      overruns++;
-      // advance time to reflect overrun
-      tNext = micros();
-    } else {
-      // wait for time to write next block
-      while(micros() < tNext);
+    if (tw < minWriteTime) {
+      minWriteTime = tw;
     }
     }
+    nWrite++;
   }
   }
-  // total write time
-  t = micros() - t;
-
+  uint32_t endTime = millis();
+  uint32_t avgWriteTime = totalWriteTime/BLOCK_COUNT;
   // end multiple block write mode
   // end multiple block write mode
   if (!sd.card()->writeStop()) {
   if (!sd.card()->writeStop()) {
     error("writeStop failed");
     error("writeStop failed");
   }
   }
 
 
-  cout << F("Done\n");
-  cout << F("Elapsed time: ") << setprecision(3)<< 1.e-6*t;
+  cout << F("\nDone\n");
+  cout << F("maxQueueSize: ") << maxQueueSize << endl;
+  cout << F("Elapsed time: ") << setprecision(3)<< 1.e-3*(endTime - startTime);
   cout << F(" seconds\n");
   cout << F(" seconds\n");
-  cout << F("Max write time: ") << maxWriteTime << F(" micros\n");
-  cout << F("Overruns: ") << overruns << endl;
-  if (overruns) {
-    uint8_t n = overruns > OVER_DIM ? OVER_DIM : overruns;
-    cout << F("fileBlock,micros") << endl;
-    for (uint8_t i = 0; i < n; i++) {
-      cout << over[i].block << ',' << over[i].micros << endl;
-    }
-  }
+  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");  
   // close file for next pass of loop
   // close file for next pass of loop
   file.close();
   file.close();
   Serial.println();
   Serial.println();

+ 139 - 0
SdFat/examples/ReadCsvArray/ReadCsvArray.ino

@@ -0,0 +1,139 @@
+// Read a two dimensional array from a CSV file.
+//
+#include <SPI.h>
+#include <SdFat.h>
+#define CS_PIN SS
+
+// 5 X 4 array
+#define ROW_DIM 5
+#define COL_DIM 4
+
+SdFat SD;
+File file;
+
+/*
+ * Read a file one field at a time.
+ *
+ * file - File to read.
+ *
+ * str - Character array for the field.
+ *
+ * size - Size of str array.
+ *
+ * delim - String containing field delimiters.
+ *
+ * return - length of field including terminating delimiter.
+ *
+ * Note, the last character of str will not be a delimiter if
+ * a read error occurs, the field is too long, or the file
+ * does not end with a delimiter.  Consider this an error
+ * if not at end-of-file.
+ *
+ */
+size_t readField(File* file, char* str, size_t size, const char* delim) {
+  char ch;
+  size_t n = 0;
+  while ((n + 1) < size && file->read(&ch, 1) == 1) {
+    // Delete CR.
+    if (ch == '\r') {
+      continue;
+    }
+    str[n++] = ch;
+    if (strchr(delim, ch)) {
+        break;
+    }
+  }
+  str[n] = '\0';
+  return n;
+}
+//------------------------------------------------------------------------------
+#define errorHalt(msg) {Serial.println(F(msg)); SysCall::halt();}
+//------------------------------------------------------------------------------
+void setup() {
+  Serial.begin(9600);
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  Serial.println("Type any character to start");
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
+  // 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) {
+    errorHalt("open failed");
+  }
+  // Rewind file so test data is not appended.
+  file.rewind();
+
+  // Write test data.
+  file.print(F(
+    "11,12,13,14\r\n"
+    "21,22,23,24\r\n"
+    "31,32,33,34\r\n"
+    "41,42,43,44\r\n"
+    "51,52,53,54"     // Allow missing endl at eof.
+    ));
+
+  // Rewind the file for read.
+  file.rewind();
+
+  // Array for data.
+  int array[ROW_DIM][COL_DIM];
+  int i = 0;     // First array index.
+  int j = 0;     // Second array index
+  size_t n;      // Length of returned field with delimiter.
+  char str[20];  // Must hold longest field with delimiter and zero byte.
+  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");
+      if (n == 0) {
+        errorHalt("Too few lines");
+      }
+      array[i][j] = strtol(str, &ptr, 10);
+      if (ptr == str) {
+        errorHalt("bad number");
+      }
+      while (*ptr == ' ') {
+        ptr++;
+      }
+      if (*ptr != ',' && *ptr != '\n' && *ptr != '\0') {
+        errorHalt("extra characters in field");
+      }
+      if (j < (COL_DIM-1) && str[n-1] != ',') {
+        errorHalt("line with too few fields");
+      }
+    }
+    // Allow missing endl at eof.
+    if (str[n-1] != '\n' && file.available()) {
+      errorHalt("missing endl");
+    }    
+  }
+
+  // Print the array.
+  for (i = 0; i < ROW_DIM; i++) {
+    for (j = 0; j < COL_DIM; j++) {
+      if (j) {
+        Serial.print(' ');
+      }
+      Serial.print(array[i][j]);
+    }
+    Serial.println();
+  }
+  Serial.println("Done");
+  file.close();
+}
+//------------------------------------------------------------------------------
+void loop() {
+}
+

+ 120 - 0
SdFat/examples/ReadCsvStream/ReadCsvStream.ino

@@ -0,0 +1,120 @@
+/*
+ *  This example reads a simple CSV, comma-separated values, file.
+ *  Each line of the file has a label and three values, a long and two floats.
+ */
+#include <SPI.h>
+#include "SdFat.h"
+
+// SD chip select pin
+const uint8_t chipSelect = SS;
+
+// file system object
+SdFat sd;
+
+// create Serial stream
+ArduinoOutStream cout(Serial);
+
+char fileName[] = "testfile.csv";
+//------------------------------------------------------------------------------
+// store error strings in flash to save RAM
+#define error(s) sd.errorHalt(F(s))
+//------------------------------------------------------------------------------
+// read and print CSV test file
+void readFile() {
+  long lg = 0;
+  float f1, f2;
+  char text[10];
+  char c1, c2, c3;  // space for commas.
+
+  // open input file
+  ifstream sdin(fileName);
+
+  // check for open error
+  if (!sdin.is_open()) {
+    error("open");
+  }
+
+  // read until input fails
+  while (1) {
+    // Get text field.
+    sdin.get(text, sizeof(text), ',');
+
+    // Assume EOF if fail.
+    if (sdin.fail()) {
+      break;
+    }
+
+    // Get commas and numbers.
+    sdin >> c1 >> lg >> c2 >> f1 >> c3 >> f2;
+
+    // Skip CR/LF.
+    sdin.skipWhite();
+
+    if (sdin.fail()) {
+      error("bad input");
+    }
+
+    // error in line if not commas
+    if (c1 != ',' || c2 != ',' || c3 != ',') {
+      error("comma");
+    }
+
+    // print in six character wide columns
+    cout << text << setw(6) << lg << setw(6) << f1 << setw(6) << f2 << endl;
+  }
+  // Error in an input line if file is not at EOF.
+  if (!sdin.eof()) {
+    error("readFile");
+  }
+}
+//------------------------------------------------------------------------------
+// write test file
+void writeFile() {
+
+  // create or open and truncate output file
+  ofstream sdout(fileName);
+
+  // write file from string stored in flash
+  sdout << F(
+          "Line 1,1,2.3,4.5\n"
+          "Line 2,6,7.8,9.0\n"
+          "Line 3,9,8.7,6.5\n"
+          "Line 4,-4,-3.2,-1\n") << flush;
+
+  // check for any errors
+  if (!sdout) {
+    error("writeFile");
+  }
+
+  sdout.close();
+}
+//------------------------------------------------------------------------------
+void setup() {
+  Serial.begin(9600);
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  cout << F("Type any character to start\n");
+  while (!Serial.available()) {
+    SysCall::yield();  
+  }
+
+  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
+  // breadboards.  use SPI_FULL_SPEED for better performance
+  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
+    sd.initErrorHalt();
+  }
+
+  // create test file
+  writeFile();
+
+  cout << endl;
+
+  // read and print test
+  readFile();
+
+  cout << "\nDone!" << endl;
+}
+void loop() {}

+ 4 - 3
SdFat/examples/ReadWrite/ReadWrite.ino

@@ -20,7 +20,7 @@
 #define SD_CS_PIN SS
 #define SD_CS_PIN SS
 #include <SPI.h>
 #include <SPI.h>
 //#include <SD.h>
 //#include <SD.h>
-#include <SdFat.h>
+#include "SdFat.h"
 SdFat SD;
 SdFat SD;
 
 
 File myFile;
 File myFile;
@@ -29,11 +29,12 @@ void setup()
 {
 {
   // Open serial communications and wait for port to open:
   // Open serial communications and wait for port to open:
   Serial.begin(9600);
   Serial.begin(9600);
+  
+  // Wait for USB Serial 
   while (!Serial) {
   while (!Serial) {
-    ; // wait for serial port to connect. Needed for Leonardo only
+    SysCall::yield();
   }
   }
 
 
-
   Serial.print("Initializing SD card...");
   Serial.print("Initializing SD card...");
   // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
   // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
   // Note that even if it's not used as the CS pin, the hardware SS pin
   // Note that even if it's not used as the CS pin, the hardware SS pin

+ 9 - 5
SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino

@@ -21,17 +21,21 @@ const int chipSelect = 4;
 
 
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 SdFat sd;
 SdFat sd;
 SdFile myFile;
 SdFile myFile;
 
 
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   Serial.println("Type any character to start");
   Serial.println("Type any character to start");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
-
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   // Initialize SdFat or print a detailed error message and halt
   // Initialize SdFat or print a detailed error message and halt
   // Use half speed like the native library.
   // Use half speed like the native library.
   // change to SPI_FULL_SPEED for more performance.
   // change to SPI_FULL_SPEED for more performance.

+ 28 - 13
SdFat/examples/SdFormatter/SdFormatter.ino

@@ -14,9 +14,9 @@
 // Print extra info for debug if DEBUG_PRINT is nonzero
 // Print extra info for debug if DEBUG_PRINT is nonzero
 #define DEBUG_PRINT 0
 #define DEBUG_PRINT 0
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 #if DEBUG_PRINT
 #if DEBUG_PRINT
-#include <SdFatUtil.h>
+#include "FreeStack.h"
 #endif  // DEBUG_PRINT
 #endif  // DEBUG_PRINT
 //
 //
 // Change the value of chipSelect if your hardware does
 // Change the value of chipSelect if your hardware does
@@ -74,12 +74,12 @@ void sdError_F(const __FlashStringHelper* str) {
     cout << F("SD error: ") << hex << int(card.errorCode());
     cout << F("SD error: ") << hex << int(card.errorCode());
     cout << ',' << int(card.errorData()) << dec << endl;
     cout << ',' << int(card.errorData()) << dec << endl;
   }
   }
-  while (1);
+  SysCall::halt();
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 #if DEBUG_PRINT
 #if DEBUG_PRINT
 void debugPrint() {
 void debugPrint() {
-  cout << F("FreeRam: ") << FreeRam() << endl;
+  cout << F("FreeStack: ") << FreeStack() << endl;
   cout << F("partStart: ") << relSector << endl;
   cout << F("partStart: ") << relSector << endl;
   cout << F("partSize: ") << partSize << endl;
   cout << F("partSize: ") << partSize << endl;
   cout << F("reserved: ") << reservedSectors << endl;
   cout << F("reserved: ") << reservedSectors << endl;
@@ -440,8 +440,18 @@ void formatCard() {
 void setup() {
 void setup() {
   char c;
   char c;
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
-
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  cout << F("Type any character to start\n");
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
+  // Discard any extra characters.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
   cout << F(
   cout << F(
          "\n"
          "\n"
          "This program can erase and/or format SD/SDHC cards.\n"
          "This program can erase and/or format SD/SDHC cards.\n"
@@ -455,8 +465,9 @@ void setup() {
          "\n"
          "\n"
          "Warning, all data on the card will be erased.\n"
          "Warning, all data on the card will be erased.\n"
          "Enter 'Y' to continue: ");
          "Enter 'Y' to continue: ");
-  while (!Serial.available()) {}
-  delay(400);  // catch Due restart problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   c = Serial.read();
   c = Serial.read();
   cout << c << endl;
   cout << c << endl;
@@ -464,8 +475,10 @@ void setup() {
     cout << F("Quiting, you did not enter 'Y'.\n");
     cout << F("Quiting, you did not enter 'Y'.\n");
     return;
     return;
   }
   }
-  // read any existing Serial data
-  while (Serial.read() >= 0) {}
+  // Read any existing Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
   cout << F(
   cout << F(
          "\n"
          "\n"
@@ -476,7 +489,9 @@ void setup() {
          "\n"
          "\n"
          "Enter option: ");
          "Enter option: ");
 
 
-  while (!Serial.available()) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   c = Serial.read();
   c = Serial.read();
   cout << c << endl;
   cout << c << endl;
   if (!strchr("EFQ", c)) {
   if (!strchr("EFQ", c)) {
@@ -497,8 +512,8 @@ void setup() {
   }
   }
   cardCapacityMB = (cardSizeBlocks + 2047)/2048;
   cardCapacityMB = (cardSizeBlocks + 2047)/2048;
 
 
-  cout << F("Card Size: ") << cardCapacityMB;
-  cout << F(" MB, (MB = 1,048,576 bytes)") << endl;
+  cout << F("Card Size: ") << setprecision(0) << 1.048576*cardCapacityMB;
+  cout << F(" MB, (MB = 1,000,000 bytes)") << endl;
 
 
   if (c == 'E' || c == 'F') {
   if (c == 'E' || c == 'F') {
     eraseCard();
     eraseCard();

+ 16 - 9
SdFat/examples/SdInfo/SdInfo.ino

@@ -2,7 +2,7 @@
  * This program attempts to initialize an SD card and analyze its structure.
  * This program attempts to initialize an SD card and analyze its structure.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 /*
 /*
  * SD chip select pin.  Common values are:
  * SD chip select pin.  Common values are:
  *
  *
@@ -139,18 +139,22 @@ void volDmp() {
   cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl;
   cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl;
   if (sd.vol()->dataStartBlock() % eraseSize) {
   if (sd.vol()->dataStartBlock() % eraseSize) {
     cout << F("Data area is not aligned on flash erase boundaries!\n");
     cout << F("Data area is not aligned on flash erase boundaries!\n");
-    cout << F("Download and use formatter from www.sdsd.card()->org/consumer!\n");
+    cout << F("Download and use formatter from www.sdcard.org!\n");
   }
   }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while(!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 
 
   // use uppercase in hex and use 0X base prefix
   // use uppercase in hex and use 0X base prefix
   cout << uppercase << showbase << endl;
   cout << uppercase << showbase << endl;
 
 
-  // pstr stores strings in flash to save RAM
+  // F stores strings in flash to save RAM
   cout << F("SdFat version: ") << SD_FAT_VERSION << endl;
   cout << F("SdFat version: ") << SD_FAT_VERSION << endl;
   if (DISABLE_CHIP_SELECT < 0) {
   if (DISABLE_CHIP_SELECT < 0) {
     cout << F(
     cout << F(
@@ -167,13 +171,16 @@ void setup() {
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void loop() {
 void loop() {
-  // read any existing Serial data
-  while (Serial.read() >= 0) {}
+  // Read any existing Serial data.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
-  // pstr stores strings in flash to save RAM
+  // F stores strings in flash to save RAM
   cout << F("\ntype any character to start\n");
   cout << F("\ntype any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   uint32_t t = millis();
   uint32_t t = millis();
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with

+ 14 - 4
SdFat/examples/SoftwareSpi/SoftwareSpi.ino

@@ -4,7 +4,7 @@
 // This example will also run on an Uno and other boards using software SPI.
 // This example will also run on an Uno and other boards using software SPI.
 //
 //
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 #if SD_SPI_CONFIGURATION >= 3  // Must be set in SdFat/SdFatConfig.h
 #if SD_SPI_CONFIGURATION >= 3  // Must be set in SdFat/SdFatConfig.h
 //
 //
 // Pin numbers in templates must be constants.
 // Pin numbers in templates must be constants.
@@ -23,10 +23,14 @@ SdFile file;
 
 
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // Wait for Leonardo
-
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   Serial.println("Type any character to start");
   Serial.println("Type any character to start");
-  while (Serial.read() <= 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   if (!sd.begin(SD_CHIP_SELECT_PIN)) {
   if (!sd.begin(SD_CHIP_SELECT_PIN)) {
     sd.initErrorHalt();
     sd.initErrorHalt();
@@ -37,6 +41,12 @@ void setup() {
   }
   }
   file.println(F("This line was printed using software SPI."));
   file.println(F("This line was printed using software SPI."));
 
 
+  file.rewind();
+  
+  while (file.available()) {
+    Serial.write(file.read());
+  }
+
   file.close();
   file.close();
 
 
   Serial.println(F("Done."));
   Serial.println(F("Done."));

+ 18 - 15
SdFat/examples/StdioBench/StdioBench.ino

@@ -1,6 +1,6 @@
 // Benchmark comparing SdFile and StdioStream.
 // Benchmark comparing SdFile and StdioStream.
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // Define PRINT_FIELD nonzero to use printField.
 // Define PRINT_FIELD nonzero to use printField.
 #define PRINT_FIELD 0
 #define PRINT_FIELD 0
@@ -17,24 +17,27 @@ StdioStream stdioFile;
 
 
 float f[100];
 float f[100];
 char buf[20];
 char buf[20];
-char* label[] =
+const char* label[] =
 { "uint8_t 0 to 255, 100 times ", "uint16_t 0 to 20000",
 { "uint8_t 0 to 255, 100 times ", "uint16_t 0 to 20000",
   "uint32_t 0 to 20000", "uint32_t 1000000000 to 1000010000",
   "uint32_t 0 to 20000", "uint32_t 1000000000 to 1000010000",
   "float nnn.ffff, 10000 times"
   "float nnn.ffff, 10000 times"
 };
 };
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
-  uint32_t m;
   uint32_t printSize;
   uint32_t printSize;
-  uint32_t stdioSize;
+  uint32_t stdioSize = 0;
   uint32_t printTime;
   uint32_t printTime;
-  uint32_t stdioTime;
+  uint32_t stdioTime = 0;
 
 
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}
+  while (!Serial) {
+    SysCall::yield();
+  }
 
 
   Serial.println(F("Type any character to start"));
   Serial.println(F("Type any character to start"));
-  while (!Serial.available());
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   Serial.println(F("Starting test"));
   Serial.println(F("Starting test"));
   if (!sd.begin(SD_CS_PIN)) {
   if (!sd.begin(SD_CS_PIN)) {
     sd.errorHalt();
     sd.errorHalt();
@@ -48,7 +51,7 @@ void setup() {
     for (uint8_t fileType = 0; fileType < 2; fileType++) {
     for (uint8_t fileType = 0; fileType < 2; fileType++) {
       if (!fileType) {
       if (!fileType) {
         if (!printFile.open("print.txt", O_CREAT | O_RDWR | O_TRUNC)) {
         if (!printFile.open("print.txt", O_CREAT | O_RDWR | O_TRUNC)) {
-          Serial.println("open fail");
+          Serial.println(F("open fail"));
           return;
           return;
         }
         }
         printTime = millis();
         printTime = millis();
@@ -95,7 +98,7 @@ void setup() {
 
 
       } else {
       } else {
         if (!stdioFile.fopen("stream.txt", "w+")) {
         if (!stdioFile.fopen("stream.txt", "w+")) {
-          Serial.println("fopen fail");
+          Serial.println(F("fopen fail"));
           return;
           return;
         }
         }
         stdioTime = millis();
         stdioTime = millis();
@@ -186,22 +189,22 @@ void setup() {
       }
       }
     }
     }
 
 
-    Serial.print("fileSize: ");
+    Serial.print(F("fileSize: "));
     if (printSize != stdioSize) {
     if (printSize != stdioSize) {
       Serial.print(printSize);
       Serial.print(printSize);
-      Serial.print(" != ");
+      Serial.print(F(" != "));
     }
     }
     Serial.println(stdioSize);
     Serial.println(stdioSize);
-    Serial.print("print millis: ");
+    Serial.print(F("print millis: "));
     Serial.println(printTime);
     Serial.println(printTime);
-    Serial.print("stdio millis: ");
+    Serial.print(F("stdio millis: "));
     Serial.println(stdioTime);
     Serial.println(stdioTime);
-    Serial.print("ratio: ");
+    Serial.print(F("ratio: "));
     Serial.println((float)printTime/(float)stdioTime);
     Serial.println((float)printTime/(float)stdioTime);
     Serial.println();
     Serial.println();
     printFile.close();
     printFile.close();
     stdioFile.fclose();
     stdioFile.fclose();
   }
   }
-  Serial.println("Done");
+  Serial.println(F("Done"));
 }
 }
 void loop() {}
 void loop() {}

+ 17 - 14
SdFat/examples/ThreeCards/ThreeCards.ino

@@ -2,8 +2,8 @@
  * Example use of three SD cards.
  * Example use of three SD cards.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 #if SD_SPI_CONFIGURATION >= 3  // Must be set in SdFat/SdFatConfig.h
 #if SD_SPI_CONFIGURATION >= 3  // Must be set in SdFat/SdFatConfig.h
 
 
 // SD1 is a microSD on hardware SPI pins 50-52
 // SD1 is a microSD on hardware SPI pins 50-52
@@ -45,19 +45,22 @@ void list() {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-  Serial.print(F("FreeRam: "));
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  Serial.print(F("FreeStack: "));
 
 
-  Serial.println(FreeRam());
+  Serial.println(FreeStack());
 
 
   // fill buffer with known data
   // fill buffer with known data
-  for (int i = 0; i < sizeof(buf); i++) {
+  for (size_t i = 0; i < sizeof(buf); i++) {
     buf[i] = i;
     buf[i] = i;
   }
   }
-
   Serial.println(F("type any character to start"));
   Serial.println(F("type any character to start"));
-  while (Serial.read() <= 0) {}
-
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   // disable sd2 while initializing sd1
   // disable sd2 while initializing sd1
   pinMode(SD2_CS, OUTPUT);
   pinMode(SD2_CS, OUTPUT);
   digitalWrite(SD2_CS, HIGH);
   digitalWrite(SD2_CS, HIGH);
@@ -140,7 +143,7 @@ void setup() {
   Serial.println(F("Writing SD1:/Dir1/TEST1.bin"));
   Serial.println(F("Writing SD1:/Dir1/TEST1.bin"));
 
 
   // write data to /Dir1/TEST1.bin on sd1
   // write data to /Dir1/TEST1.bin on sd1
-  for (int i = 0; i < NWRITE; i++) {
+  for (uint16_t i = 0; i < NWRITE; i++) {
     if (file1.write(buf, sizeof(buf)) != sizeof(buf)) {
     if (file1.write(buf, sizeof(buf)) != sizeof(buf)) {
       sd1.errorExit("sd1.write");
       sd1.errorExit("sd1.write");
     }
     }
@@ -168,7 +171,7 @@ void setup() {
     if (n == 0) {
     if (n == 0) {
       break;
       break;
     }
     }
-    if (file2.write(buf, n) != n) {
+    if ((int)file2.write(buf, n) != n) {
       sd2.errorExit("write3");
       sd2.errorExit("write3");
     }
     }
   }
   }
@@ -196,7 +199,7 @@ void setup() {
     if (n != sizeof(buf)) {
     if (n != sizeof(buf)) {
       sd2.errorExit("read2");
       sd2.errorExit("read2");
     }
     }
-    if (file3.write(buf, n) != n) {
+    if ((int)file3.write(buf, n) != n) {
       sd3.errorExit("write2");
       sd3.errorExit("write2");
     }
     }
   }
   }
@@ -206,11 +209,11 @@ void setup() {
   // Verify content of file3
   // Verify content of file3
   file3.rewind();
   file3.rewind();
   Serial.println(F("Verifying content of TEST3.bin"));
   Serial.println(F("Verifying content of TEST3.bin"));
-  for (int i = 0; i < NWRITE; i++) {
+  for (uint16_t i = 0; i < NWRITE; i++) {
     if (file3.read(buf, sizeof(buf)) != sizeof(buf)) {
     if (file3.read(buf, sizeof(buf)) != sizeof(buf)) {
       sd3.errorExit("sd3.read");
       sd3.errorExit("sd3.read");
     }
     }
-    for (int j = 0; j < sizeof(buf); j++) {
+    for (size_t j = 0; j < sizeof(buf); j++) {
       if (j != buf[j]) {
       if (j != buf[j]) {
         sd3.errorExit("Verify error");
         sd3.errorExit("Verify error");
       }
       }

+ 9 - 7
SdFat/examples/Timestamp/Timestamp.ino

@@ -3,7 +3,7 @@
  * and the timestamp() function.
  * and the timestamp() function.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 SdFat sd;
 SdFat sd;
 
 
@@ -75,12 +75,14 @@ void printTimestamps(SdFile& f) {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup(void) {
 void setup(void) {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  // Wait for USB Serial
+  while (!Serial) {
+    SysCall::yield();
+  }
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (!Serial.available());
-  delay(400);  // catch Due reset problem
-
+  while (!Serial.available()) {
+    SysCall::yield();  
+  }
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.
   if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
   if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
@@ -170,4 +172,4 @@ void setup(void) {
   cout << F("\nDone\n");
   cout << F("\nDone\n");
 }
 }
 
 
-void loop(void) {}
+void loop() {}

+ 14 - 10
SdFat/examples/TwoCards/TwoCards.ino

@@ -2,8 +2,8 @@
  * Example use of two SD cards.
  * Example use of two SD cards.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 
 SdFat sd1;
 SdFat sd1;
 const uint8_t SD1_CS = 10;  // chip select for sd1
 const uint8_t SD1_CS = 10;  // chip select for sd1
@@ -24,19 +24,23 @@ const uint16_t NWRITE = FILE_SIZE/BUF_DIM;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-  Serial.print(F("FreeRam: "));
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  Serial.print(F("FreeStack: "));
 
 
-  Serial.println(FreeRam());
+  Serial.println(FreeStack());
 
 
   // fill buffer with known data
   // fill buffer with known data
-  for (int i = 0; i < sizeof(buf); i++) {
+  for (size_t i = 0; i < sizeof(buf); i++) {
     buf[i] = i;
     buf[i] = i;
   }
   }
 
 
   Serial.println(F("type any character to start"));
   Serial.println(F("type any character to start"));
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   // disable sd2 while initializing sd1
   // disable sd2 while initializing sd1
   pinMode(SD2_CS, OUTPUT);
   pinMode(SD2_CS, OUTPUT);
@@ -102,7 +106,7 @@ void setup() {
   Serial.println(F("Writing test.bin to sd1"));
   Serial.println(F("Writing test.bin to sd1"));
 
 
   // write data to /Dir1/test.bin on sd1
   // write data to /Dir1/test.bin on sd1
-  for (int i = 0; i < NWRITE; i++) {
+  for (uint16_t i = 0; i < NWRITE; i++) {
     if (file1.write(buf, sizeof(buf)) != sizeof(buf)) {
     if (file1.write(buf, sizeof(buf)) != sizeof(buf)) {
       sd1.errorExit("sd1.write");
       sd1.errorExit("sd1.write");
     }
     }
@@ -129,7 +133,7 @@ void setup() {
     if (n == 0) {
     if (n == 0) {
       break;
       break;
     }
     }
-    if (file2.write(buf, n) != n) {
+    if ((int)file2.write(buf, n) != n) {
       sd2.errorExit("write2");
       sd2.errorExit("write2");
     }
     }
   }
   }

+ 81 - 0
SdFat/examples/VolumeFreeSpace/VolumeFreeSpace.ino

@@ -0,0 +1,81 @@
+/*
+ * This program demonstrates the freeClusterCount() call.
+ */
+#include <SPI.h>
+#include "SdFat.h"
+/*
+ * SD chip select pin.  Common values are:
+ *
+ * Arduino Ethernet shield, pin 4.
+ * SparkFun SD shield, pin 8.
+ * Adafruit Datalogging shield, pin 10.
+ * Default SD chip select is the SPI SS pin.
+ */
+const uint8_t chipSelect = SS;
+
+#define TEST_FILE "Cluster.test"
+// file system
+SdFat sd;
+
+// test file
+SdFile file;
+
+// Serial output stream
+ArduinoOutStream cout(Serial);
+//------------------------------------------------------------------------------
+void printFreeSpace() {
+  cout << F("freeClusterCount() call time: ");
+  uint32_t m = micros();
+  uint32_t volFree = sd.vol()->freeClusterCount();
+  cout << micros() - m << F(" micros\n");
+  cout << F("freeClusters: ") <<  volFree << setprecision(3) << endl;
+  float fs = 0.000512*volFree*sd.vol()->blocksPerCluster();
+  cout << F("freeSpace: ") << fs << F(" MB (MB = 1,000,000 bytes)\n\n");
+}
+//------------------------------------------------------------------------------
+void setup() {
+  Serial.begin(9600);
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  if (!MAINTAIN_FREE_CLUSTER_COUNT) {
+    cout << F("Please edit SdFatConfig.h and set\n");
+    cout << F("MAINTAIN_FREE_CLUSTER_COUNT nonzero for\n");
+    cout << F("maximum freeClusterCount() performance.\n\n");
+  }
+  // F stores strings in flash to save RAM
+  cout << F("Type any character to start\n");
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
+  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
+  // breadboards.  use SPI_FULL_SPEED for better performance.
+  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
+    sd.initErrorHalt();
+  }
+  // Insure no TEST_FILE. 
+  sd.remove(TEST_FILE);
+  
+  cout << F("\nFirst call to freeClusterCount scans the FAT.\n\n");
+  printFreeSpace();
+  
+  cout << F("Create and write to ") << TEST_FILE << endl;
+  if (!file.open(TEST_FILE, O_WRITE | O_CREAT)) {
+    sd.errorHalt(F("Create failed"));
+  }
+  file.print(F("Cause a cluster to be allocated"));
+  file.close();
+  
+  cout << F("\nSecond freeClusterCount call is faster if\n");
+  cout << F("MAINTAIN_FREE_CLUSTER_COUNT is nonzero.\n\n");
+  
+  printFreeSpace();
+
+  cout << F("Remove ") << TEST_FILE << endl << endl;
+  sd.remove(TEST_FILE);
+  printFreeSpace();
+  cout << F("Done") << endl;
+}
+//------------------------------------------------------------------------------
+void loop() {}

+ 32 - 15
SdFat/examples/bench/bench.ino

@@ -2,8 +2,8 @@
  * This program is a simple binary write/read benchmark.
  * This program is a simple binary write/read benchmark.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -15,10 +15,10 @@ const size_t BUF_SIZE = 512;
 const uint32_t FILE_SIZE_MB = 5;
 const uint32_t FILE_SIZE_MB = 5;
 
 
 // Write pass count.
 // Write pass count.
-const uint8_t WRITE_COUNT = 10;
+const uint8_t WRITE_COUNT = 2;
 
 
 // Read pass count.
 // Read pass count.
-const uint8_t READ_COUNT = 5;
+const uint8_t READ_COUNT = 2;
 //==============================================================================
 //==============================================================================
 // End of configuration constants.
 // End of configuration constants.
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -29,6 +29,10 @@ uint8_t buf[BUF_SIZE];
 
 
 // file system
 // file system
 SdFat sd;
 SdFat sd;
+// Set SD_SPI_CONFIGURATION to three to test next two definitions.
+// SdFatLibSpi sd;
+// Args are misoPin, mosiPin, sckPin.
+// SdFatSoftSpi<6, 7, 5> sd;
 
 
 // test file
 // test file
 SdFile file;
 SdFile file;
@@ -36,7 +40,7 @@ SdFile file;
 // Serial output stream
 // Serial output stream
 ArduinoOutStream cout(Serial);
 ArduinoOutStream cout(Serial);
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-// store error strings in flash to save RAM
+// Store error strings in flash to save RAM.
 #define error(s) sd.errorHalt(F(s))
 #define error(s) sd.errorHalt(F(s))
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void cidDmp() {
 void cidDmp() {
@@ -62,7 +66,11 @@ void cidDmp() {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(1000);
   delay(1000);
   cout << F("\nUse a freshly formatted SD for best performance.\n");
   cout << F("\nUse a freshly formatted SD for best performance.\n");
 
 
@@ -77,15 +85,18 @@ void loop() {
   uint32_t minLatency;
   uint32_t minLatency;
   uint32_t totalLatency;
   uint32_t totalLatency;
 
 
-  // discard any input
-  while (Serial.read() >= 0) {}
+  // Discard any input.
+  do {
+    delay(10);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
   // F( stores strings in flash to save RAM
   // F( stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
-  cout << F("Free RAM: ") << FreeRam() << endl;
+  cout << F("FreeStack: ") << FreeStack() << endl;
 
 
   // initialize the SD card at SPI_FULL_SPEED for best performance.
   // initialize the SD card at SPI_FULL_SPEED for best performance.
   // try SPI_HALF_SPEED if bus errors occur.
   // try SPI_HALF_SPEED if bus errors occur.
@@ -129,7 +140,9 @@ void loop() {
     for (uint32_t i = 0; i < n; i++) {
     for (uint32_t i = 0; i < n; i++) {
       uint32_t m = micros();
       uint32_t m = micros();
       if (file.write(buf, sizeof(buf)) != sizeof(buf)) {
       if (file.write(buf, sizeof(buf)) != sizeof(buf)) {
-        error("write failed");
+        sd.errorPrint("write failed");
+        file.close();
+        return;
       }
       }
       m = micros() - m;
       m = micros() - m;
       if (maxLatency < m) {
       if (maxLatency < m) {
@@ -146,11 +159,11 @@ void loop() {
     cout << s/t <<',' << maxLatency << ',' << minLatency;
     cout << s/t <<',' << maxLatency << ',' << minLatency;
     cout << ',' << totalLatency/n << endl;
     cout << ',' << totalLatency/n << endl;
   }
   }
-
   cout << endl << F("Starting read test, please wait.") << endl;
   cout << endl << F("Starting read test, please wait.") << endl;
   cout << endl <<F("read speed and latency") << endl;
   cout << endl <<F("read speed and latency") << endl;
   cout << F("speed,max,min,avg") << endl;
   cout << F("speed,max,min,avg") << endl;
   cout << F("KB/Sec,usec,usec,usec") << endl;
   cout << F("KB/Sec,usec,usec,usec") << endl;
+
   // do read test
   // do read test
   for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
   for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
     file.rewind();
     file.rewind();
@@ -161,8 +174,11 @@ void loop() {
     for (uint32_t i = 0; i < n; i++) {
     for (uint32_t i = 0; i < n; i++) {
       buf[BUF_SIZE-1] = 0;
       buf[BUF_SIZE-1] = 0;
       uint32_t m = micros();
       uint32_t m = micros();
-      if (file.read(buf, sizeof(buf)) != sizeof(buf)) {
-        error("read failed");
+      int32_t nr = file.read(buf, sizeof(buf)); 
+      if (nr != sizeof(buf)) {   
+        sd.errorPrint("read failed");
+        file.close();
+        return;
       }
       }
       m = micros() - m;
       m = micros() - m;
       if (maxLatency < m) {
       if (maxLatency < m) {
@@ -176,6 +192,7 @@ void loop() {
         error("data check");
         error("data check");
       }
       }
     }
     }
+    s = file.fileSize();
     t = millis() - t;
     t = millis() - t;
     cout << s/t <<',' << maxLatency << ',' << minLatency;
     cout << s/t <<',' << maxLatency << ',' << minLatency;
     cout << ',' << totalLatency/n << endl;
     cout << ',' << totalLatency/n << endl;

+ 14 - 7
SdFat/examples/dataLogger/dataLogger.ino

@@ -2,7 +2,7 @@
  * Simple data logger.
  * Simple data logger.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin.  Be sure to disable any other SPI devices such as Enet.
 // SD chip select pin.  Be sure to disable any other SPI devices such as Enet.
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -11,7 +11,7 @@ const uint8_t chipSelect = SS;
 // The interval must be greater than the maximum SD write latency plus the
 // The interval must be greater than the maximum SD write latency plus the
 // time to acquire and write data to the SD to avoid overrun errors.
 // time to acquire and write data to the SD to avoid overrun errors.
 // Run the bench example to check the quality of your SD card.
 // Run the bench example to check the quality of your SD card.
-const uint32_t SAMPLE_INTERVAL_MS = 200;
+const uint32_t SAMPLE_INTERVAL_MS = 1000;
 
 
 // Log file base name.  Must be six characters or less.
 // Log file base name.  Must be six characters or less.
 #define FILE_BASE_NAME "Data"
 #define FILE_BASE_NAME "Data"
@@ -67,12 +67,18 @@ void setup() {
   char fileName[13] = FILE_BASE_NAME "00.csv";
   char fileName[13] = FILE_BASE_NAME "00.csv";
 
 
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(1000);
   delay(1000);
 
 
   Serial.println(F("Type any character to start"));
   Serial.println(F("Type any character to start"));
-  while (!Serial.available()) {}
-
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
+  
   // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.
   if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
   if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
@@ -96,9 +102,10 @@ void setup() {
   if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) {
   if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) {
     error("file.open");
     error("file.open");
   }
   }
+  // Read any Serial data.
   do {
   do {
     delay(10);
     delay(10);
-  } while (Serial.read() >= 0);
+  } while (Serial.available() && Serial.read() >= 0);
 
 
   Serial.print(F("Logging to: "));
   Serial.print(F("Logging to: "));
   Serial.println(fileName);
   Serial.println(fileName);
@@ -138,6 +145,6 @@ void loop() {
     // Close file and stop.
     // Close file and stop.
     file.close();
     file.close();
     Serial.println(F("Done"));
     Serial.println(F("Done"));
-    while(1) {}
+    SysCall::halt();
   }
   }
 }
 }

+ 33 - 28
SdFat/examples/directoryFunctions/directoryFunctions.ino

@@ -1,13 +1,12 @@
 /*
 /*
  * Example use of chdir(), ls(), mkdir(), and  rmdir().
  * Example use of chdir(), ls(), mkdir(), and  rmdir().
  */
  */
-#include <SPI.h>
-#include <SdFat.h>
+#include <SPI.h> 
+#include "SdFat.h"
+
 // SD card chip select pin.
 // SD card chip select pin.
 const uint8_t SD_CHIP_SELECT = SS;
 const uint8_t SD_CHIP_SELECT = SS;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-// Permit SD to be wiped if ALLOW_WIPE is true.
-const bool ALLOW_WIPE = false;
 
 
 // File system object.
 // File system object.
 SdFat sd;
 SdFat sd;
@@ -29,40 +28,44 @@ ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(1000);
   delay(1000);
 
 
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
   // Wait for input line and discard.
   // Wait for input line and discard.
   cin.readline();
   cin.readline();
-
+  cout << endl;
+  
   // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.
   if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
   if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
     sd.initErrorHalt();
     sd.initErrorHalt();
   }
   }
+  if (sd.exists("Folder1") 
+    || sd.exists("Folder1/file1.txt")
+    || sd.exists("Folder1/File2.txt")) {
+    error("Please remove existing Folder1, file1.txt, and File2.txt");
+  }
 
 
-  // Check for empty SD.
-  if (file.openNext(sd.vwd(), O_READ)) {
-    cout << F("Found files/folders in the root directory.\n");
-    if (!ALLOW_WIPE) {
-      error("SD not empty, use a blank SD or set ALLOW_WIPE true.");
-    } else {
-      cout << F("Type: 'WIPE' to delete all SD files.\n");
-      char buf[10];
-      cin.readline();
-      cin.get(buf, sizeof(buf));
-      if (cin.fail() || strncmp(buf, "WIPE", 4) || buf[4] >= ' ') {
-        error("Invalid WIPE input");
-      }
-      file.close();
-      if (!sd.vwd()->rmRfStar()) {
-        error("wipe failed");
-      }
-      cout << F("***SD wiped clean.***\n\n");
+  int rootFileCount = 0;
+  sd.vwd()->rewind(); 
+  while (file.openNext(sd.vwd(), O_READ)) {
+    if (!file.isHidden()) {
+      rootFileCount++;
+    }
+    file.close();
+    if (rootFileCount > 10) {
+      error("Too many files in root. Please use an empty SD.");
     }
     }
   }
   }
-
+  if (rootFileCount) {
+    cout << F("\nPlease use an empty SD for best results.\n\n");
+    delay(1000);
+  }
   // Create a new folder.
   // Create a new folder.
   if (!sd.mkdir("Folder1")) {
   if (!sd.mkdir("Folder1")) {
     error("Create Folder1 failed");
     error("Create Folder1 failed");
@@ -89,7 +92,7 @@ void setup() {
   file.close();
   file.close();
   cout << F("Created File2.txt in current directory\n");
   cout << F("Created File2.txt in current directory\n");
 
 
-  cout << F("List of files on the SD.\n");
+  cout << F("\nList of files on the SD.\n");
   sd.ls("/", LS_R);
   sd.ls("/", LS_R);
 
 
   // Remove files from current directory.
   // Remove files from current directory.
@@ -103,7 +106,7 @@ void setup() {
     error("chdir to root failed.\n");
     error("chdir to root failed.\n");
   }
   }
 
 
-  cout << F("List of files on the SD.\n");
+  cout << F("\nList of files on the SD.\n");
   sd.ls(LS_R);
   sd.ls(LS_R);
 
 
   // Remove Folder1.
   // Remove Folder1.
@@ -111,7 +114,9 @@ void setup() {
     error("rmdir for Folder1 failed\n");
     error("rmdir for Folder1 failed\n");
   }
   }
 
 
-  cout << F("\nFolder1 removed, SD empty.\n");
+  cout << F("\nFolder1 removed.\n");
+  cout << F("\nList of files on the SD.\n");
+  sd.ls(LS_R);
   cout << F("Done!\n");
   cout << F("Done!\n");
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 9 - 3
SdFat/examples/fgets/fgets.ino

@@ -1,6 +1,6 @@
 // Demo of fgets function to read lines from a file.
 // Demo of fgets function to read lines from a file.
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -60,10 +60,16 @@ void makeTestFile() {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup(void) {
 void setup(void) {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // Wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 
 
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   delay(400);  // catch Due reset problem
   delay(400);  // catch Due reset problem
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with

+ 5 - 2
SdFat/examples/formatting/formatting.ino

@@ -3,7 +3,7 @@
  * Format dates
  * Format dates
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // create Serial stream
 // create Serial stream
 ArduinoOutStream cout(Serial);
 ArduinoOutStream cout(Serial);
@@ -42,7 +42,10 @@ void showDate(int m, int d, int y) {
 void setup(void) {
 void setup(void) {
   Serial.begin(9600);
   Serial.begin(9600);
 
 
-  while (!Serial) {}  // wait for Leonardo
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(2000);
   delay(2000);
 
 
   cout << endl << "default formatting" << endl;
   cout << endl << "default formatting" << endl;

+ 10 - 5
SdFat/examples/getline/getline.ino

@@ -7,7 +7,7 @@
  * may not the best way to read a file.
  * may not the best way to read a file.
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -54,12 +54,17 @@ void testGetline() {
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup(void) {
 void setup(void) {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 
 
-  // pstr stores strings in flash to save RAM
+  // F stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.

+ 192 - 95
SdFat/examples/readCSV/readCSV.ino

@@ -1,115 +1,212 @@
-/*
- *  This example reads a simple CSV, comma-separated values, file.
- *  Each line of the file has a label and three values, a long and two floats.
- */
-#include <SPI.h>
-#include <SdFat.h>
 
 
-// SD chip select pin
-const uint8_t chipSelect = SS;
-
-// file system object
-SdFat sd;
+// Functions to read a CSV text file one field at a time.
+//
+#include <limits.h>
+#include <SPI.h>
 
 
-// create Serial stream
-ArduinoOutStream cout(Serial);
+// next line for SD.h
+//#include <SD.h>
 
 
-char fileName[] = "testfile.csv";
-//------------------------------------------------------------------------------
-// store error strings in flash to save RAM
-#define error(s) sd.errorHalt(F(s))
-//------------------------------------------------------------------------------
-// read and print CSV test file
-void readFile() {
-  long lg;
-  float f1, f2;
-  char text[10];
-  char c1, c2, c3;  // space for commas.
+// next two lines for SdFat
+#include <SdFat.h>
+SdFat SD;
 
 
-  // open input file
-  ifstream sdin(fileName);
+#define CS_PIN SS
 
 
-  // check for open error
-  if (!sdin.is_open()) {
-    error("open");
-  }
+// example can use comma or semicolon
+#define CSV_DELIM ','
 
 
-  // read until input fails
-  while (1) {
-    // Get text field.
-    sdin.get(text, sizeof(text), ',');
+File file;
 
 
-    // Assume EOF if fail.
-    if (sdin.fail()) {
+/*
+ * Read a file one field at a time.
+ *
+ * file - File to read.
+ *
+ * str - Character array for the field.
+ *
+ * size - Size of str array.
+ *
+ * delim - csv delimiter.
+ *
+ * return - negative value for failure.
+ *          delimiter, '\n' or zero(EOF) for success.           
+ */
+int csvReadText(File* file, char* str, size_t size, char delim) {
+  char ch;
+  int rtn;
+  size_t n = 0;
+  while (true) {
+    // check for EOF
+    if (!file->available()) {
+      rtn = 0;
       break;
       break;
     }
     }
-
-    // Get commas and numbers.
-    sdin >> c1 >> lg >> c2 >> f1 >> c3 >> f2;
-
-    // Skip CR/LF.
-    sdin.skipWhite();
-
-    if (sdin.fail()) {
-      error("bad input");
+    if (file->read(&ch, 1) != 1) {
+      // read error
+      rtn = -1;
+      break;
     }
     }
-
-    // error in line if not commas
-    if (c1 != ',' || c2 != ',' || c3 != ',') {
-      error("comma");
+    // Delete CR.
+    if (ch == '\r') {
+      continue;
     }
     }
-
-    // print in six character wide columns
-    cout << text << setw(6) << lg << setw(6) << f1 << setw(6) << f2 << endl;
-  }
-  // Error in an input line if file is not at EOF.
-  if (!sdin.eof()) {
-    error("readFile");
+    if (ch == delim || ch == '\n') {
+      rtn = ch;
+      break;
+    }
+    if ((n+1) >= size) {
+      // string too long
+      rtn = -2;
+      n--;
+      break;
+    }
+    str[n++] = ch;
   }
   }
+  str[n] = '\0';
+  return rtn;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-// write test file
-void writeFile() {
-
-  // create or open and truncate output file
-  ofstream sdout(fileName);
-
-  // write file from string stored in flash
-  sdout << F(
-          "Line 1,1,2.3,4.5\n"
-          "Line 2,6,7.8,9.0\n"
-          "Line 3,9,8.7,6.5\n"
-          "Line 4,-4,-3.2,-1\n") << flush;
-
-  // check for any errors
-  if (!sdout) {
-    error("writeFile");
-  }
-
-  sdout.close();
+int csvReadInt32(File* file, int32_t* num, char delim) {
+  char buf[20];
+  char* ptr;
+  int rtn = csvReadText(file, buf, sizeof(buf), delim);
+  if (rtn < 0) return rtn;
+  *num = strtol(buf, &ptr, 10);
+  if (buf == ptr) return -3;
+  while(isspace(*ptr)) ptr++;
+  return *ptr == 0 ? rtn : -4;
+}
+//------------------------------------------------------------------------------
+int csvReadInt16(File* file, int16_t* num, char delim) {
+  int32_t tmp;
+  int rtn = csvReadInt32(file, &tmp, delim);
+  if (rtn < 0) return rtn;
+  if (tmp < INT_MIN || tmp > INT_MAX) return -5;
+  *num = tmp;
+  return rtn;
+}
+//------------------------------------------------------------------------------
+int csvReadUint32(File* file, uint32_t* num, char delim) {
+  char buf[20];
+  char* ptr;
+  int rtn = csvReadText(file, buf, sizeof(buf), delim);
+  if (rtn < 0) return rtn;
+  *num = strtoul(buf, &ptr, 10);
+  if (buf == ptr) return -3;
+  while(isspace(*ptr)) ptr++;
+  return *ptr == 0 ? rtn : -4;
+}
+//------------------------------------------------------------------------------
+int csvReadUint16(File* file, uint16_t* num, char delim) {
+  uint32_t tmp;
+  int rtn = csvReadUint32(file, &tmp, delim);
+  if (rtn < 0) return rtn;
+  if (tmp > UINT_MAX) return -5;
+  *num = tmp;
+  return rtn;
+}
+//------------------------------------------------------------------------------
+int csvReadDouble(File* file, double* num, char delim) {
+  char buf[20];
+  char* ptr;
+  int rtn = csvReadText(file, buf, sizeof(buf), delim);
+  if (rtn < 0) return rtn;
+  *num = strtod(buf, &ptr);
+  if (buf == ptr) return -3;
+  while(isspace(*ptr)) ptr++;
+  return *ptr == 0 ? rtn : -4;
+}
+//------------------------------------------------------------------------------
+int csvReadFloat(File* file, float* num, char delim) {
+  double tmp;
+  int rtn = csvReadDouble(file, &tmp, delim);
+  if (rtn < 0)return rtn;
+  // could test for too large.
+  *num = tmp;
+  return rtn;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
-  cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
-
-  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
-  // breadboards.  use SPI_FULL_SPEED for better performance
-  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
-    sd.initErrorHalt();
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    yield();
   }
   }
-
-  // create test file
-  writeFile();
-
-  cout << endl;
-
-  // read and print test
-  readFile();
-
-  cout << "\nDone!" << endl;
+  Serial.println("Type any character to start");
+  while (!Serial.available()) {
+    yield();
+  }
+  // Initialize the SD.
+  if (!SD.begin(CS_PIN)) {
+    Serial.println("begin failed");
+    return;
+  }
+  // Remove existing file.
+   SD.remove("READTEST.TXT"); 
+   
+  // Create the file.
+  file = SD.open("READTEST.TXT", FILE_WRITE);
+  if (!file) {
+    Serial.println("open failed");
+    return;
+  }
+  // Write test data.
+  file.print(F(
+#if CSV_DELIM == ','
+    "36,23.20,20.70,57.60,79.50,01:08:14,23.06.16\r\n"
+    "37,23.21,20.71,57.61,79.51,02:08:14,23.07.16\r\n"
+#elif CSV_DELIM == ';'
+    "36;23.20;20.70;57.60;79.50;01:08:14;23.06.16\r\n"
+    "37;23.21;20.71;57.61;79.51;02:08:14;23.07.16\r\n"
+#else
+#error "Bad CSV_DELIM"
+#endif
+));
+
+  // Rewind the file for read.
+  file.seek(0);
+
+  // Read the file and print fields.
+  int16_t tcalc; 
+  float t1, t2, h1, h2;
+  // Must be dim 9 to allow for zero byte.
+  char timeS[9], dateS[9];
+  while (file.available()) {
+    if (csvReadInt16(&file, &tcalc, CSV_DELIM) != CSV_DELIM
+      || csvReadFloat(&file, &t1, CSV_DELIM) != CSV_DELIM
+      || csvReadFloat(&file, &t2, CSV_DELIM) != CSV_DELIM
+      || csvReadFloat(&file, &h1, CSV_DELIM) != CSV_DELIM
+      || csvReadFloat(&file, &h2, CSV_DELIM) != CSV_DELIM
+      || csvReadText(&file, timeS, sizeof(timeS), CSV_DELIM) != CSV_DELIM
+      || csvReadText(&file, dateS, sizeof(dateS), CSV_DELIM) != '\n') {
+      Serial.println("read error");
+      int ch;
+      int nr = 0;
+      // print part of file after error.
+      while ((ch = file.read()) > 0 && nr++ < 100) {
+        Serial.write(ch);
+      }
+      break;            
+    }
+    Serial.print(tcalc);
+    Serial.print(CSV_DELIM);
+    Serial.print(t1);
+    Serial.print(CSV_DELIM);
+    Serial.print(t2);
+    Serial.print(CSV_DELIM);
+    Serial.print(h1);
+    Serial.print(CSV_DELIM);
+    Serial.print(h2);
+    Serial.print(CSV_DELIM);
+    Serial.print(timeS);
+    Serial.print(CSV_DELIM);
+    Serial.println(dateS);
+  }
+  file.close();
 }
 }
-void loop() {}
+//------------------------------------------------------------------------------
+void loop() {
+}
+

+ 9 - 5
SdFat/examples/rename/rename.ino

@@ -3,7 +3,7 @@
  * and SdFat::rename().
  * and SdFat::rename().
  */
  */
 #include <SPI.h>
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 
 // SD chip select pin
 // SD chip select pin
 const uint8_t chipSelect = SS;
 const uint8_t chipSelect = SS;
@@ -19,11 +19,15 @@ ArduinoOutStream cout(Serial);
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void setup() {
 void setup() {
   Serial.begin(9600);
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   cout << F("Insert an empty SD.  Type any character to start.") << endl;
   cout << F("Insert an empty SD.  Type any character to start.") << endl;
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
 
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   // breadboards.  use SPI_FULL_SPEED for better performance.

+ 38 - 0
SdFat/examples/wipe/wipe.ino

@@ -0,0 +1,38 @@
+// Example to wipe all data from an already formatted SD.
+#include <SPI.h>
+#include "SdFat.h"
+const int chipSelect = SS;
+
+SdFat sd;
+
+void setup() {
+  int c;
+  Serial.begin(9600);
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  Serial.println("Type 'Y' to wipe all data.");
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
+  c = Serial.read();
+  if (c != 'Y') {
+    sd.errorHalt("Quitting, you did not type 'Y'.");
+  }
+  if (!sd.begin(chipSelect)) {
+    sd.initErrorHalt();
+  }
+  // Use wipe() for no dot progress indicator.
+  if (!sd.wipe(&Serial)) {
+    sd.errorHalt("Wipe failed.");
+  }
+  // Must reinitialize after wipe.
+  if (!sd.begin(chipSelect)) {
+    sd.errorHalt("Second init failed.");
+  }
+  Serial.println("Done");
+}
+
+void loop() {
+}

+ 9 - 0
SdFat/library.properties

@@ -0,0 +1,9 @@
+name=SdFat
+version=2015.4.26
+author=
+maintainer=
+sentence=FAT16/FAT32 file system for SD cards.
+paragraph=
+category=Uncategorized
+url=
+architectures=*

+ 0 - 0
SdFat/utility/ArduinoFiles.h → SdFat/src/FatLib/ArduinoFiles.h


+ 10 - 2
SdFat/utility/ArduinoStream.h → SdFat/src/FatLib/ArduinoStream.h

@@ -25,7 +25,7 @@
  */
  */
 #include "FatLibConfig.h"
 #include "FatLibConfig.h"
 #if ENABLE_ARDUINO_FEATURES
 #if ENABLE_ARDUINO_FEATURES
-#include <Arduino.h>
+#include "SysCall.h"
 #include "bufstream.h"
 #include "bufstream.h"
 //==============================================================================
 //==============================================================================
 /**
 /**
@@ -50,7 +50,9 @@ class ArduinoInStream : public ibufstream {
     size_t i = 0;
     size_t i = 0;
     uint32_t t;
     uint32_t t;
     m_line[0] = '\0';
     m_line[0] = '\0';
-    while (!m_hw->available()) {}
+    while (!m_hw->available()) {
+      SysCall::yield();
+    }
 
 
     while (1) {
     while (1) {
       t = millis();
       t = millis();
@@ -77,6 +79,8 @@ done:
    * \return true/false.
    * \return true/false.
    */
    */
   bool seekoff(off_type off, seekdir way) {
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
     return false;
   }
   }
   /** Internal - do not use.
   /** Internal - do not use.
@@ -84,6 +88,7 @@ done:
    * \return true/false.
    * \return true/false.
    */
    */
   bool seekpos(pos_type pos) {
   bool seekpos(pos_type pos) {
+    (void)pos;
     return false;
     return false;
   }
   }
 
 
@@ -121,9 +126,12 @@ class ArduinoOutStream : public ostream {
     m_pr->write(str);
     m_pr->write(str);
   }
   }
   bool seekoff(off_type off, seekdir way) {
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
     return false;
   }
   }
   bool seekpos(pos_type pos) {
   bool seekpos(pos_type pos) {
+    (void)pos;
     return false;
     return false;
   }
   }
   bool sync() {
   bool sync() {

+ 0 - 0
SdFat/utility/FatApiConstants.h → SdFat/src/FatLib/FatApiConstants.h


+ 4 - 4
SdFat/utility/FatFile.cpp → SdFat/src/FatLib/FatFile.cpp

@@ -847,10 +847,6 @@ dir_t* FatFile::readDirCache(bool skipReadOk) {
       }
       }
       goto fail;
       goto fail;
     }
     }
-//   if (read(&b, 1) != 1) {
-//     DBG_FAIL_MACRO;
-//     goto fail;
-//    }
     m_curPosition += 31;
     m_curPosition += 31;
   } else {
   } else {
     m_curPosition += 32;
     m_curPosition += 32;
@@ -1107,6 +1103,10 @@ bool FatFile::seekSet(uint32_t pos) {
     DBG_FAIL_MACRO;
     DBG_FAIL_MACRO;
     goto fail;
     goto fail;
   }
   }
+  // Optimize O_APPEND writes.
+  if (pos == m_curPosition) {
+    return true;
+  }
   if (pos == 0) {
   if (pos == 0) {
     // set position to start of file
     // set position to start of file
     m_curCluster = 0;
     m_curCluster = 0;

+ 1 - 8
SdFat/utility/FatFile.h → SdFat/src/FatLib/FatFile.h

@@ -37,10 +37,6 @@ class FatFileSystem;
 #ifdef __AVR__
 #ifdef __AVR__
 #include <avr/pgmspace.h>
 #include <avr/pgmspace.h>
 #else  // __AVR__
 #else  // __AVR__
-#ifndef PGM_P
-/** pointer to flash for ARM */
-#define PGM_P const char*
-#endif  // PGM_P
 #ifndef PSTR
 #ifndef PSTR
 /** store literal string in flash for ARM */
 /** store literal string in flash for ARM */
 #define PSTR(x) (x)
 #define PSTR(x) (x)
@@ -55,7 +51,7 @@ class FatFileSystem;
 #endif  // pgm_read_word
 #endif  // pgm_read_word
 #ifndef PROGMEM
 #ifndef PROGMEM
 /** store in flash for ARM */
 /** store in flash for ARM */
-#define PROGMEM const
+#define PROGMEM
 #endif  // PROGMEM
 #endif  // PROGMEM
 #endif  // __AVR__
 #endif  // __AVR__
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -219,9 +215,6 @@ class FatFile {
    */
    */
   bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
   bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
   /** Create and open a new contiguous file of a specified size.
   /** Create and open a new contiguous file of a specified size.
-   *
-   * \note This function only supports short DOS 8.3 names.
-   * See open() for more information.
    *
    *
    * \param[in] dirFile The directory where the file will be created.
    * \param[in] dirFile The directory where the file will be created.
    * \param[in] path A path with a valid DOS 8.3 file name.
    * \param[in] path A path with a valid DOS 8.3 file name.

+ 0 - 0
SdFat/utility/FatFileLFN.cpp → SdFat/src/FatLib/FatFileLFN.cpp


+ 0 - 0
SdFat/utility/FatFilePrint.cpp → SdFat/src/FatLib/FatFilePrint.cpp


+ 0 - 0
SdFat/utility/FatFileSFN.cpp → SdFat/src/FatLib/FatFileSFN.cpp


+ 10 - 1
SdFat/utility/FatFileSystem.h → SdFat/src/FatLib/FatFileSystem.h

@@ -84,6 +84,15 @@ class FatFileSystem : public  FatVolume {
     tmpFile.open(vwd(), path, mode);
     tmpFile.open(vwd(), path, mode);
     return tmpFile;
     return tmpFile;
   }
   }
+  /** open a file
+   *
+   * \param[in] path location of file to be opened.
+   * \param[in] mode open mode flags.
+   * \return a File object.
+   */
+  File open(const String &path, uint8_t mode = FILE_READ) {
+    return open(path.c_str(), mode );
+  }
 #endif  // ENABLE_ARDUINO_FEATURES
 #endif  // ENABLE_ARDUINO_FEATURES
   /** Change a volume's working directory to root
   /** Change a volume's working directory to root
    *
    *
@@ -180,7 +189,7 @@ fail:
    *
    *
    * LS_R - Recursive list of subdirectories.
    * LS_R - Recursive list of subdirectories.
    */
    */
-  void ls(print_t* pr, uint8_t flags) {
+  void ls(print_t* pr, uint8_t flags = 0) {
     vwd()->ls(pr, flags);
     vwd()->ls(pr, flags);
   }
   }
   //----------------------------------------------------------------------------
   //----------------------------------------------------------------------------

+ 0 - 0
SdFat/utility/FatLib.h → SdFat/src/FatLib/FatLib.h


+ 2 - 2
SdFat/utility/FatLibConfig.h → SdFat/src/FatLib/FatLibConfig.h

@@ -25,7 +25,7 @@
 #define FatLibConfig_h
 #define FatLibConfig_h
 #include <stdint.h>
 #include <stdint.h>
 // Allow this file to override defaults.
 // Allow this file to override defaults.
-#include "../SdFatConfig.h"
+#include "SdFatConfig.h"
 
 
 #ifdef __AVR__
 #ifdef __AVR__
 #include <avr/io.h>
 #include <avr/io.h>
@@ -134,7 +134,7 @@
  *  Enable Extra features for Arduino.
  *  Enable Extra features for Arduino.
  */
  */
 #ifndef ENABLE_ARDUINO_FEATURES
 #ifndef ENABLE_ARDUINO_FEATURES
-#if defined(ARDUINO) || defined(DOXYGEN)
+#if defined(ARDUINO) || defined(PLATFORM_ID) || defined(DOXYGEN)
 #define ENABLE_ARDUINO_FEATURES 1
 #define ENABLE_ARDUINO_FEATURES 1
 #else  //  #if defined(ARDUINO) || defined(DOXYGEN)
 #else  //  #if defined(ARDUINO) || defined(DOXYGEN)
 #define ENABLE_ARDUINO_FEATURES 0
 #define ENABLE_ARDUINO_FEATURES 0

+ 122 - 0
SdFat/utility/FatStructs.h → SdFat/src/FatLib/FatStructs.h

@@ -120,6 +120,128 @@ struct masterBootRecord {
 /** Type name for masterBootRecord */
 /** Type name for masterBootRecord */
 typedef struct masterBootRecord mbr_t;
 typedef struct masterBootRecord mbr_t;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+/** 
+ * \struct biosParmBlock
+ *
+ * \brief BIOS parameter block
+ * 
+ *  The BIOS parameter block describes the physical layout of a FAT volume.
+ */
+struct biosParmBlock {
+          /**
+           * Count of bytes per sector. This value may take on only the
+           * following values: 512, 1024, 2048 or 4096
+           */
+  uint16_t bytesPerSector;
+          /**
+           * Number of sectors per allocation unit. This value must be a
+           * power of 2 that is greater than 0. The legal values are
+           * 1, 2, 4, 8, 16, 32, 64, and 128.
+           */
+  uint8_t  sectorsPerCluster;
+          /**
+           * Number of sectors before the first FAT.
+           * This value must not be zero.
+           */
+  uint16_t reservedSectorCount;
+          /** The count of FAT data structures on the volume. This field should
+           *  always contain the value 2 for any FAT volume of any type.
+           */
+  uint8_t  fatCount;
+          /**
+          * For FAT12 and FAT16 volumes, this field contains the count of
+          * 32-byte directory entries in the root directory. For FAT32 volumes,
+          * this field must be set to 0. For FAT12 and FAT16 volumes, this
+          * value should always specify a count that when multiplied by 32
+          * results in a multiple of bytesPerSector.  FAT16 volumes should
+          * use the value 512.
+          */
+  uint16_t rootDirEntryCount;
+          /**
+           * This field is the old 16-bit total count of sectors on the volume.
+           * This count includes the count of all sectors in all four regions
+           * of the volume. This field can be 0; if it is 0, then totalSectors32
+           * must be nonzero.  For FAT32 volumes, this field must be 0. For
+           * FAT12 and FAT16 volumes, this field contains the sector count, and
+           * totalSectors32 is 0 if the total sector count fits
+           * (is less than 0x10000).
+           */
+  uint16_t totalSectors16;
+          /**
+           * This dates back to the old MS-DOS 1.x media determination and is
+           * no longer usually used for anything.  0xF8 is the standard value
+           * for fixed (nonremovable) media. For removable media, 0xF0 is
+           * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
+           */
+  uint8_t  mediaType;
+          /**
+           * Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
+           * On FAT32 volumes this field must be 0, and sectorsPerFat32
+           * contains the FAT size count.
+           */
+  uint16_t sectorsPerFat16;
+           /** Sectors per track for interrupt 0x13. Not used otherwise. */
+  uint16_t sectorsPerTrtack;
+           /** Number of heads for interrupt 0x13.  Not used otherwise. */
+  uint16_t headCount;
+          /**
+           * Count of hidden sectors preceding the partition that contains this
+           * FAT volume. This field is generally only relevant for media
+           *  visible on interrupt 0x13.
+           */
+  uint32_t hidddenSectors;
+          /**
+           * This field is the new 32-bit total count of sectors on the volume.
+           * This count includes the count of all sectors in all four regions
+           * of the volume.  This field can be 0; if it is 0, then
+           * totalSectors16 must be nonzero.
+           */
+  uint32_t totalSectors32;
+          /**
+           * Count of sectors occupied by one FAT on FAT32 volumes.
+           */
+  uint32_t sectorsPerFat32;
+          /**
+           * This field is only defined for FAT32 media and does not exist on
+           * FAT12 and FAT16 media.
+           * Bits 0-3 -- Zero-based number of active FAT.
+           *             Only valid if mirroring is disabled.
+           * Bits 4-6 -- Reserved.
+           * Bit 7	-- 0 means the FAT is mirrored at runtime into all FATs.
+	         *        -- 1 means only one FAT is active; it is the one referenced in bits 0-3.
+           * Bits 8-15 	-- Reserved.
+           */
+  uint16_t fat32Flags;
+          /**
+           * FAT32 version. High byte is major revision number.
+           * Low byte is minor revision number. Only 0.0 define.
+           */
+  uint16_t fat32Version;
+          /**
+           * Cluster number of the first cluster of the root directory for FAT32.
+           * This usually 2 but not required to be 2.
+           */
+  uint32_t fat32RootCluster;
+          /**
+           * Sector number of FSINFO structure in the reserved area of the
+           * FAT32 volume. Usually 1.
+           */
+  uint16_t fat32FSInfo;
+          /**
+           * If nonzero, indicates the sector number in the reserved area
+           * of the volume of a copy of the boot record. Usually 6.
+           * No value other than 6 is recommended.
+           */
+  uint16_t fat32BackBootBlock;
+          /**
+           * Reserved for future expansion. Code that formats FAT32 volumes
+           * should always set all of the bytes of this field to 0.
+           */
+  uint8_t  fat32Reserved[12];
+} __attribute__((packed));
+/** Type name for biosParmBlock */
+typedef struct biosParmBlock bpb_t;
+//------------------------------------------------------------------------------
 /**
 /**
  * \struct fat_boot
  * \struct fat_boot
  *
  *

+ 16 - 0
SdFat/utility/FatVolume.cpp → SdFat/src/FatLib/FatVolume.cpp

@@ -103,6 +103,7 @@ bool FatVolume::allocateCluster(uint32_t current, uint32_t* next) {
     // Remember place for search start.
     // Remember place for search start.
     m_allocSearchStart = find;
     m_allocSearchStart = find;
   }
   }
+  updateFreeClusterCount(-1);
   *next = find;
   *next = find;
   return true;
   return true;
 
 
@@ -171,6 +172,9 @@ bool FatVolume::allocContiguous(uint32_t count, uint32_t* firstCluster) {
     }
     }
     endCluster--;
     endCluster--;
   }
   }
+  // Maintain count of free clusters.
+  updateFreeClusterCount(-count);
+
   // return first cluster number to caller
   // return first cluster number to caller
   *firstCluster = bgnCluster;
   *firstCluster = bgnCluster;
   return true;
   return true;
@@ -337,6 +341,9 @@ bool FatVolume::freeChain(uint32_t cluster) {
       DBG_FAIL_MACRO;
       DBG_FAIL_MACRO;
       goto fail;
       goto fail;
     }
     }
+    // Add one to count of free clusters.
+    updateFreeClusterCount(1);
+
     if (cluster < m_allocSearchStart) {
     if (cluster < m_allocSearchStart) {
       m_allocSearchStart = cluster;
       m_allocSearchStart = cluster;
     }
     }
@@ -350,6 +357,11 @@ fail:
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 int32_t FatVolume::freeClusterCount() {
 int32_t FatVolume::freeClusterCount() {
+#if MAINTAIN_FREE_CLUSTER_COUNT
+  if (m_freeClusterCount >= 0) {
+    return m_freeClusterCount;
+  }
+#endif  // MAINTAIN_FREE_CLUSTER_COUNT
   uint32_t free = 0;
   uint32_t free = 0;
   uint32_t lba;
   uint32_t lba;
   uint32_t todo = m_lastCluster + 1;
   uint32_t todo = m_lastCluster + 1;
@@ -399,6 +411,7 @@ int32_t FatVolume::freeClusterCount() {
     DBG_FAIL_MACRO;
     DBG_FAIL_MACRO;
     goto fail;
     goto fail;
   }
   }
+  setFreeClusterCount(free);
   return free;
   return free;
 
 
 fail:
 fail:
@@ -488,6 +501,9 @@ bool FatVolume::init(uint8_t part) {
   clusterCount >>= m_clusterSizeShift;
   clusterCount >>= m_clusterSizeShift;
   m_lastCluster = clusterCount + 1;
   m_lastCluster = clusterCount + 1;
 
 
+  // Indicate unknown number of free clusters.
+  setFreeClusterCount(-1);
+
   // FAT type is determined by cluster count
   // FAT type is determined by cluster count
   if (clusterCount < 4085) {
   if (clusterCount < 4085) {
     m_fatType = 12;
     m_fatType = 12;

+ 22 - 6
SdFat/utility/FatVolume.h → SdFat/src/FatLib/FatVolume.h

@@ -24,6 +24,7 @@
  * \brief FatVolume class
  * \brief FatVolume class
  */
  */
 #include <stddef.h>
 #include <stddef.h>
+#include "SysCall.h"
 #include "FatLibConfig.h"
 #include "FatLibConfig.h"
 #include "FatStructs.h"
 #include "FatStructs.h"
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -31,11 +32,10 @@
 /** Macro for debug. */
 /** Macro for debug. */
 #define DEBUG_MODE 0
 #define DEBUG_MODE 0
 #if DEBUG_MODE
 #if DEBUG_MODE
-#include <Arduino.h>
 #define DBG_FAIL_MACRO Serial.print(F(__FILE__)); Serial.println(__LINE__)
 #define DBG_FAIL_MACRO Serial.print(F(__FILE__)); Serial.println(__LINE__)
 #define DBG_PRINT_IF(b) if (b) {Serial.println(F(#b)); DBG_FAIL_MACRO;}
 #define DBG_PRINT_IF(b) if (b) {Serial.println(F(#b)); DBG_FAIL_MACRO;}
 #define DBG_HALT_IF(b) if (b) {Serial.println(F(#b));\
 #define DBG_HALT_IF(b) if (b) {Serial.println(F(#b));\
-                               DBG_FAIL_MACRO; while (1);}
+                               DBG_FAIL_MACRO; SysCall::halt();}
 #else  // DEBUG_MODE
 #else  // DEBUG_MODE
 #define DBG_FAIL_MACRO
 #define DBG_FAIL_MACRO
 #define DBG_PRINT_IF(b)
 #define DBG_PRINT_IF(b)
@@ -44,12 +44,9 @@
 #endif  // DOXYGEN_SHOULD_SKIP_THIS
 #endif  // DOXYGEN_SHOULD_SKIP_THIS
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 #if ENABLE_ARDUINO_FEATURES
 #if ENABLE_ARDUINO_FEATURES
-#include <Arduino.h>
-/** Use Print on Arduino */
+/** Use Print for Arduino */
 typedef Print print_t;
 typedef Print print_t;
 #else  // ENABLE_ARDUINO_FEATURES
 #else  // ENABLE_ARDUINO_FEATURES
-//  Arduino type for flash string.
-class __FlashStringHelper;
 /**
 /**
  * \class CharWriter
  * \class CharWriter
  * \brief Character output - often serial port.
  * \brief Character output - often serial port.
@@ -272,6 +269,25 @@ class FatVolume {
   uint32_t m_lastCluster;          // Last cluster number in FAT.
   uint32_t m_lastCluster;          // Last cluster number in FAT.
   uint32_t m_rootDirStart;         // Start block for FAT16, cluster for FAT32.
   uint32_t m_rootDirStart;         // Start block for FAT16, cluster for FAT32.
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+#if MAINTAIN_FREE_CLUSTER_COUNT
+  int32_t  m_freeClusterCount;     // Count of free clusters in volume.
+  void setFreeClusterCount(int32_t value) {
+    m_freeClusterCount = value;
+  }
+  void updateFreeClusterCount(int32_t change) {
+    if (m_freeClusterCount >= 0) {
+      m_freeClusterCount += change;
+    }
+  }
+#else  // MAINTAIN_FREE_CLUSTER_COUNT
+  void setFreeClusterCount(int32_t value) {
+    (void)value;
+  }
+  void updateFreeClusterCount(int32_t change) {
+    (void)change;
+  }
+#endif  // MAINTAIN_FREE_CLUSTER_COUNT
+
 // block caches
 // block caches
   FatCache m_cache;
   FatCache m_cache;
 #if USE_SEPARATE_FAT_CACHE
 #if USE_SEPARATE_FAT_CACHE

+ 0 - 0
SdFat/utility/FmtNumber.cpp → SdFat/src/FatLib/FmtNumber.cpp


+ 0 - 0
SdFat/utility/FmtNumber.h → SdFat/src/FatLib/FmtNumber.h


+ 6 - 90
SdFat/utility/StdioStream.cpp → SdFat/src/FatLib/StdioStream.cpp

@@ -149,16 +149,6 @@ int StdioStream::fputs(const char* str) {
   return fwrite(str, 1, len) == len ? len : EOF;
   return fwrite(str, 1, len) == len ? len : EOF;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-int StdioStream::fputs_P(PGM_P str) {
-  PGM_P bgn = str;
-  for (char c; (c = pgm_read_byte(str)); str++) {
-    if (putc(c) < 0) {
-      return EOF;
-    }
-  }
-  return str - bgn;
-}
-//------------------------------------------------------------------------------
 size_t StdioStream::fread(void* ptr, size_t size, size_t count) {
 size_t StdioStream::fread(void* ptr, size_t size, size_t count) {
   uint8_t* dst = reinterpret_cast<uint8_t*>(ptr);
   uint8_t* dst = reinterpret_cast<uint8_t*>(ptr);
   size_t total = size*count;
   size_t total = size*count;
@@ -281,8 +271,9 @@ int StdioStream::write(const void* buf, size_t count) {
   return count;
   return count;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
 size_t StdioStream::print(const __FlashStringHelper *str) {
 size_t StdioStream::print(const __FlashStringHelper *str) {
-  const char *p = (const char PROGMEM *)str;
+  const char *p = (const char*)str;
   uint8_t c;
   uint8_t c;
   while ((c = pgm_read_byte(p))) {
   while ((c = pgm_read_byte(p))) {
     if (putc(c) < 0) {
     if (putc(c) < 0) {
@@ -290,89 +281,14 @@ size_t StdioStream::print(const __FlashStringHelper *str) {
     }
     }
     p++;
     p++;
   }
   }
-  return p - (const char PROGMEM *)str;
+  return p - (const char*)str;
 }
 }
+#endif  // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 int StdioStream::printDec(float value, uint8_t prec) {
 int StdioStream::printDec(float value, uint8_t prec) {
-#define FLOAT_NEW_WAY
-#ifdef FLOAT_NEW_WAY
   char buf[24];
   char buf[24];
   char *ptr = fmtFloat(value, buf + sizeof(buf), prec);
   char *ptr = fmtFloat(value, buf + sizeof(buf), prec);
-  // return fputs(ptr);
-  // uint8_t len = buf + sizeof(buf) - ptr;
   return write(ptr, buf + sizeof(buf) - ptr);
   return write(ptr, buf + sizeof(buf) - ptr);
-#else
-  char* ptr;
-  uint8_t rtn = 0;
-  uint8_t sign = 0;
-  if (value < 0) {
-    value = -value;
-    sign = '-';
-  }
-  // check for NaN INF OVF
-  if (isnan(value)) {
-    if (fputs_P(PSTR("nan")) < 0) {
-      return -1;
-    }
-    rtn += 3;
-  } else if (isinf(value)) {
-    if (fputs_P(PSTR("inf")) < 0) {
-      return -1;
-    }
-    rtn += 3;
-  } else if (value > 4294967040.0) {
-    if (fputs_P(PSTR("ovf")) < 0) {
-      return -1;
-    }
-    rtn += 3;
-  } else {
-    if (sign) {
-      if (putc(sign) < 0) {
-        return -1;
-      }
-      rtn++;
-    }
-    if (prec > 9) {
-      prec = 9;
-    }
-
-    /*
-       uint32_t s = 1;
-       for (uint8_t i = 0; i < prec; i++) {
-         // s *= 10;
-         s = ((s << 2) + s) << 1;
-       }
-       // round value
-       value += 0.5/s;
-     */
-    value += scale10(0.5, -prec);
-    uint32_t whole = value;
-    int np;
-    if ((np = printDec(whole)) < 0) {
-      return -1;
-    }
-    rtn += np;
-    if (prec) {
-      if (putc('.') < 0) {
-        return -1;
-      }
-      char* str = fmtSpace(prec);
-      if (!str) {
-        return -1;
-      }
-      char* tmp = str - prec;
-
-      //  uint32_t fraction = s*(value - whole);
-      uint32_t fraction =  scale10(value - whole, prec);
-      ptr = fmtDec(fraction, str);
-      while (ptr > tmp) {
-        *--ptr = '0';
-      }
-      rtn += prec + 1;
-    }
-  }
-  return rtn;
-#endif
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 int StdioStream::printDec(signed char n) {
 int StdioStream::printDec(signed char n) {
@@ -532,7 +448,7 @@ int StdioStream::fillGet() {
 // private
 // private
 bool StdioStream::fillBuf() {
 bool StdioStream::fillBuf() {
   if (!(m_flags &
   if (!(m_flags &
-        F_SRD)) {  /////////////check for F_ERR and F_EOF ??/////////////////
+        F_SRD)) {  // check for F_ERR and F_EOF ??/////////////////
     if (!(m_flags & F_SRW)) {
     if (!(m_flags & F_SRW)) {
       m_flags |= F_ERR;
       m_flags |= F_ERR;
       return false;
       return false;
@@ -560,7 +476,7 @@ bool StdioStream::fillBuf() {
 // private
 // private
 bool StdioStream::flushBuf() {
 bool StdioStream::flushBuf() {
   if (!(m_flags &
   if (!(m_flags &
-        F_SWR)) {  /////////////////check for F_ERR ??////////////////////////
+        F_SWR)) {  // check for F_ERR ??////////////////////////
     if (!(m_flags & F_SRW)) {
     if (!(m_flags & F_SRW)) {
       m_flags |= F_ERR;
       m_flags |= F_ERR;
       return false;
       return false;

+ 2 - 10
SdFat/utility/StdioStream.h → SdFat/src/FatLib/StdioStream.h

@@ -278,16 +278,6 @@ class StdioStream : private FatFile {
    */
    */
   int fputs(const char* str);
   int fputs(const char* str);
   //----------------------------------------------------------------------------
   //----------------------------------------------------------------------------
-  /** Write a string stored in flash.
-   *
-   * \param[in] str string to be written.
-   *
-   * \return for success, fputs() returns a non-negative
-   * number. Otherwise, it returns EOF and sets the error indicator for
-   * the stream.
-   */
-  int fputs_P(PGM_P str);
-  //----------------------------------------------------------------------------
   /** Binary input.
   /** Binary input.
    *
    *
    * Reads an array of up to count elements, each one with a size of size
    * Reads an array of up to count elements, each one with a size of size
@@ -414,6 +404,7 @@ class StdioStream : private FatFile {
     return n < 0 ? 0 : n;
     return n < 0 ? 0 : n;
   }
   }
   //----------------------------------------------------------------------------
   //----------------------------------------------------------------------------
+#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
   /** Print a string stored in flash memory.
   /** Print a string stored in flash memory.
    *
    *
    * \param[in] str the string to print.
    * \param[in] str the string to print.
@@ -421,6 +412,7 @@ class StdioStream : private FatFile {
    * \return the number of bytes written.
    * \return the number of bytes written.
    */
    */
   size_t print(const __FlashStringHelper *str);
   size_t print(const __FlashStringHelper *str);
+#endif  // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
   //----------------------------------------------------------------------------
   //----------------------------------------------------------------------------
   /** Print a floating point number.
   /** Print a floating point number.
    *
    *

+ 67 - 0
SdFat/src/FatLib/SysCall.h

@@ -0,0 +1,67 @@
+/* FatLib Library
+ * Copyright (C) 2013 by William Greiman
+ *
+ * This file is part of the FatLib Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the FatLib Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#ifndef SysCall_h
+#define SysCall_h
+/**
+ * \file
+ * \brief SysCall class
+ */
+#if defined(ARDUINO)
+#include <Arduino.h>
+#include <SPI.h>
+#elif defined(PLATFORM_ID)  // Only defined if a Particle device
+#include "application.h"
+#else  // defined(ARDUINO)
+#error "Unknown system"
+#endif  // defined(ARDUINO)
+#ifndef F
+/** Define macro for strings stored in flash. */
+#define F(str) (str)
+#endif  // F
+/**
+ * \class SysCall
+ * \brief SysCall - Class to wrap system calls.
+ */
+class SysCall {
+ public:
+  /** Halt execution of this thread. */
+  static void halt() {
+    while (1) {
+      yield();
+    }
+  }
+  /** Yield to other threads. */
+  static void yield();
+};
+
+#if defined(ARDUINO)
+inline void SysCall::yield() {
+  // Use the external Arduino yield() function.
+  ::yield();
+}
+#elif defined(PLATFORM_ID)  // Only defined if a Particle device
+inline void SysCall::yield() {
+  Particle.process();
+}
+#else  // defined(ARDUINO)
+inline void SysCall::yield() {}
+#endif  // defined(ARDUINO)
+
+#endif  // SysCall_h

+ 4 - 0
SdFat/utility/bufstream.h → SdFat/src/FatLib/bufstream.h

@@ -65,6 +65,8 @@ class ibufstream : public istream {
     pos->position = m_pos;
     pos->position = m_pos;
   }
   }
   bool seekoff(off_type off, seekdir way) {
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
     return false;
   }
   }
   bool seekpos(pos_type pos) {
   bool seekpos(pos_type pos) {
@@ -137,6 +139,8 @@ class obufstream : public ostream {
     }
     }
   }
   }
   bool seekoff(off_type off, seekdir way) {
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
     return false;
   }
   }
   bool seekpos(pos_type pos) {
   bool seekpos(pos_type pos) {

+ 0 - 0
SdFat/utility/fstream.cpp → SdFat/src/FatLib/fstream.cpp


+ 0 - 0
SdFat/utility/fstream.h → SdFat/src/FatLib/fstream.h


+ 0 - 0
SdFat/utility/ios.h → SdFat/src/FatLib/ios.h


+ 0 - 0
SdFat/utility/iostream.h → SdFat/src/FatLib/iostream.h


+ 10 - 0
SdFat/utility/istream.cpp → SdFat/src/FatLib/istream.cpp

@@ -71,8 +71,13 @@ void istream::getBool(bool *b) {
     getNumber(b);
     getNumber(b);
     return;
     return;
   }
   }
+#ifdef __AVR__
   PGM_P truePtr = PSTR("true");
   PGM_P truePtr = PSTR("true");
   PGM_P falsePtr = PSTR("false");
   PGM_P falsePtr = PSTR("false");
+#else  // __AVR__
+  const char* truePtr = "true";
+  const char* falsePtr = "false";
+#endif  // __AVR
   const uint8_t true_len = 4;
   const uint8_t true_len = 4;
   const uint8_t false_len = 5;
   const uint8_t false_len = 5;
   bool trueOk = true;
   bool trueOk = true;
@@ -80,8 +85,13 @@ void istream::getBool(bool *b) {
   uint8_t i = 0;
   uint8_t i = 0;
   int c = readSkip();
   int c = readSkip();
   while (1) {
   while (1) {
+#ifdef __AVR__
     falseOk = falseOk && c == pgm_read_byte(falsePtr + i);
     falseOk = falseOk && c == pgm_read_byte(falsePtr + i);
     trueOk = trueOk && c == pgm_read_byte(truePtr + i);
     trueOk = trueOk && c == pgm_read_byte(truePtr + i);
+#else  // __AVR__
+    falseOk = falseOk && c == falsePtr[i];
+    trueOk = trueOk && c == truePtr[i];
+#endif  // __AVR__
     if (trueOk == false && falseOk == false) {
     if (trueOk == false && falseOk == false) {
       break;
       break;
     }
     }

+ 0 - 0
SdFat/utility/istream.h → SdFat/src/FatLib/istream.h


+ 0 - 0
SdFat/utility/ostream.cpp → SdFat/src/FatLib/ostream.cpp


+ 2 - 26
SdFat/utility/ostream.h → SdFat/src/FatLib/ostream.h

@@ -24,24 +24,6 @@
  * \brief \ref ostream class
  * \brief \ref ostream class
  */
  */
 #include "ios.h"
 #include "ios.h"
-//------------------------------------------------------------------------------
-/** macro for flash inserter */
-#define pstr(str) pgm(PSTR(str))
-/** \struct pgm
- * \brief type for string in flash
- */
-struct pgm {
-  /** Pointer to flash string */
-  char *ptr;
-  /** constructor
-   * \param[in] str initializer for pointer.
-   */
-  explicit pgm(char* str) : ptr(str) {}
-  /** constructor
-   * \param[in] str initializer for pointer.
-   */
-  explicit pgm(const char *str) : ptr(const_cast<char*>(str)) {}
-};
 //==============================================================================
 //==============================================================================
 /**
 /**
  * \class ostream
  * \class ostream
@@ -194,14 +176,7 @@ class ostream : public virtual ios {
     putNum(reinterpret_cast<uint32_t>(arg));
     putNum(reinterpret_cast<uint32_t>(arg));
     return *this;
     return *this;
   }
   }
-  /** Output a string from flash using the pstr() macro
-   * \param[in] arg pgm struct pointing to string
-   * \return the stream
-   */
-  ostream &operator<< (pgm arg) {
-    putPgm(arg.ptr);
-    return *this;
-  }
+#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
   /** Output a string from flash using the Arduino F() macro.
   /** Output a string from flash using the Arduino F() macro.
    * \param[in] arg pointing to flash string
    * \param[in] arg pointing to flash string
    * \return the stream
    * \return the stream
@@ -210,6 +185,7 @@ class ostream : public virtual ios {
     putPgm(reinterpret_cast<const char*>(arg));
     putPgm(reinterpret_cast<const char*>(arg));
     return *this;
     return *this;
   }
   }
+#endif  // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
   /**
   /**
    * Puts a character in a stream.
    * Puts a character in a stream.
    *
    *

+ 54 - 0
SdFat/src/FreeStack.h

@@ -0,0 +1,54 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2015 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#ifndef FreeStack_h
+#define FreeStack_h
+/**
+ * \file
+ * \brief FreeStack() function.
+ */
+#if defined(__AVR__) || defined(DOXYGEN)
+/** boundary between stack and heap. */
+extern char *__brkval;
+/** End of bss section.*/
+extern char __bss_end;
+/** Amount of free stack space.
+ * \return The number of free bytes.
+ */
+static int FreeStack() {
+  char top;
+  return __brkval ? &top - __brkval : &top - &__bss_end;
+}
+#elif defined(PLATFORM_ID)  // Particle board
+static int FreeStack() {
+  return System.freeMemory();
+}
+#elif defined(__arm__)
+extern "C" char* sbrk(int incr);
+static int FreeStack() {
+  char top;
+  return &top - reinterpret_cast<char*>(sbrk(0));
+}
+#else
+#warning FreeStack is not defined for this system.
+static int FreeStack() {
+  return 0;
+}
+#endif
+#endif  // FreeStack_h

+ 1 - 1
SdFat/MinimumSerial.cpp → SdFat/src/MinimumSerial.cpp

@@ -17,7 +17,7 @@
  * along with the Arduino SdFat Library.  If not, see
  * along with the Arduino SdFat Library.  If not, see
  * <http://www.gnu.org/licenses/>.
  * <http://www.gnu.org/licenses/>.
  */
  */
-#include <Arduino.h>
+#include "SystemInclude.h"
 #if defined(UDR0) || defined(DOXYGEN)
 #if defined(UDR0) || defined(DOXYGEN)
 #include "MinimumSerial.h"
 #include "MinimumSerial.h"
 const uint16_t MIN_2X_BAUD = F_CPU/(4*(2*0XFFF + 1)) + 1;
 const uint16_t MIN_2X_BAUD = F_CPU/(4*(2*0XFFF + 1)) + 1;

+ 1 - 1
SdFat/MinimumSerial.h → SdFat/src/MinimumSerial.h

@@ -19,7 +19,7 @@
  */
  */
 #ifndef MinimumSerial_h
 #ifndef MinimumSerial_h
 #define MinimumSerial_h
 #define MinimumSerial_h
-#include <Arduino.h>
+#include "SystemInclude.h"
 //==============================================================================
 //==============================================================================
 /**
 /**
  * \class MinimumSerial
  * \class MinimumSerial

+ 21 - 20
SdFat/SdFatBase.cpp → SdFat/src/SdFat.cpp

@@ -21,17 +21,12 @@
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void SdFatBase::errorHalt(Print* pr) {
 void SdFatBase::errorHalt(Print* pr) {
   errorPrint(pr);
   errorPrint(pr);
-  while (1) {}
+  SysCall::halt();
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void SdFatBase::errorHalt(Print* pr, char const* msg) {
 void SdFatBase::errorHalt(Print* pr, char const* msg) {
   errorPrint(pr, msg);
   errorPrint(pr, msg);
-  while (1) {}
-}
-//------------------------------------------------------------------------------
-void SdFatBase::errorHalt(Print* pr, const __FlashStringHelper* msg) {
-  errorPrint(pr, msg);
-  while (1) {}
+  SysCall::halt();
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void SdFatBase::errorPrint(Print* pr) {
 void SdFatBase::errorPrint(Print* pr) {
@@ -50,15 +45,9 @@ void SdFatBase::errorPrint(Print* pr, char const* msg) {
   errorPrint(pr);
   errorPrint(pr);
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-void SdFatBase::errorPrint(Print* pr, const __FlashStringHelper* msg) {
-  pr->print(F("error: "));
-  pr->println(msg);
-  errorPrint(pr);
-}
-//------------------------------------------------------------------------------
 void SdFatBase::initErrorHalt(Print* pr) {
 void SdFatBase::initErrorHalt(Print* pr) {
   initErrorPrint(pr);
   initErrorPrint(pr);
-  while (1) {}
+  SysCall::halt();
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void SdFatBase::initErrorHalt(Print* pr, char const *msg) {
 void SdFatBase::initErrorHalt(Print* pr, char const *msg) {
@@ -66,11 +55,6 @@ void SdFatBase::initErrorHalt(Print* pr, char const *msg) {
   initErrorHalt(pr);
   initErrorHalt(pr);
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-void SdFatBase::initErrorHalt(Print* pr, const __FlashStringHelper* msg) {
-  pr->println(msg);
-  initErrorHalt(pr);
-}
-//------------------------------------------------------------------------------
 void SdFatBase::initErrorPrint(Print* pr) {
 void SdFatBase::initErrorPrint(Print* pr) {
   if (cardErrorCode()) {
   if (cardErrorCode()) {
     pr->println(F("Can't access SD card. Do not reformat."));
     pr->println(F("Can't access SD card. Do not reformat."));
@@ -91,9 +75,26 @@ void SdFatBase::initErrorPrint(Print* pr, char const *msg) {
   pr->println(msg);
   pr->println(msg);
   initErrorPrint(pr);
   initErrorPrint(pr);
 }
 }
+#if defined(ARDUINO) || defined(DOXYGEN)
+//------------------------------------------------------------------------------
+void SdFatBase::errorPrint(Print* pr, const __FlashStringHelper* msg) {
+  pr->print(F("error: "));
+  pr->println(msg);
+  errorPrint(pr);
+}
+//------------------------------------------------------------------------------
+void SdFatBase::errorHalt(Print* pr, const __FlashStringHelper* msg) {
+  errorPrint(pr, msg);
+  SysCall::halt();
+}
+//------------------------------------------------------------------------------
+void SdFatBase::initErrorHalt(Print* pr, const __FlashStringHelper* msg) {
+  pr->println(msg);
+  initErrorHalt(pr);
+}
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void SdFatBase::initErrorPrint(Print* pr, const __FlashStringHelper* msg) {
 void SdFatBase::initErrorPrint(Print* pr, const __FlashStringHelper* msg) {
   pr->println(msg);
   pr->println(msg);
   initErrorPrint(pr);
   initErrorPrint(pr);
 }
 }
-
+#endif  // defined(ARDUINO) || defined(DOXYGEN)

+ 60 - 41
SdFat/SdFat.h → SdFat/src/SdFat.h

@@ -23,11 +23,16 @@
  * \file
  * \file
  * \brief SdFat class
  * \brief SdFat class
  */
  */
+#ifdef ARDUINO
+#include "SdSpiCard/SdSpiCard.h"
+#include "FatLib/FatLib.h"
+#else  // ARDUINO
 #include "SdSpiCard.h"
 #include "SdSpiCard.h"
-#include "utility/FatLib.h"
+#include "FatLib.h"
+#endif  // ARDUINO
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /** SdFat version YYYYMMDD */
 /** SdFat version YYYYMMDD */
-#define SD_FAT_VERSION 20150324
+#define SD_FAT_VERSION 20160719
 //==============================================================================
 //==============================================================================
 /**
 /**
  * \class SdBaseFile
  * \class SdBaseFile
@@ -51,7 +56,6 @@ class SdBaseFile : public FatFile {
  * \class SdFile
  * \class SdFile
  * \brief Class for backward compatibility.
  * \brief Class for backward compatibility.
  */
  */
-
 class SdFile : public PrintFile {
 class SdFile : public PrintFile {
  public:
  public:
   SdFile() {}
   SdFile() {}
@@ -108,19 +112,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    * \param[in] msg Message to print.
    */
    */
   void errorHalt(Print* pr, char const* msg);
   void errorHalt(Print* pr, char const* msg);
-  /** %Print msg, any SD error code, and halt.
-   *
-   * \param[in] msg Message to print.
-   */
-  void errorHalt(const __FlashStringHelper* msg) {
-    errorHalt(&Serial, msg);
-  }
-  /** %Print msg, any SD error code, and halt.
-   *
-   * \param[in] pr Print destination.
-   * \param[in] msg Message to print.
-   */
-  void errorHalt(Print* pr, const __FlashStringHelper* msg);
+
   /** %Print any SD error code to Serial */
   /** %Print any SD error code to Serial */
   void errorPrint() {
   void errorPrint() {
     errorPrint(&Serial);
     errorPrint(&Serial);
@@ -142,19 +134,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    * \param[in] msg Message to print.
    */
    */
   void errorPrint(Print* pr, char const* msg);
   void errorPrint(Print* pr, char const* msg);
-  /** %Print msg, any SD error code.
-   *
-   * \param[in] msg Message to print.
-   */
-  void errorPrint(const __FlashStringHelper* msg) {
-    errorPrint(&Serial, msg);
-  }
-  /** %Print msg, any SD error code.
-   *
-   * \param[in] pr Print destination.
-   * \param[in] msg Message to print.
-   */
-  void errorPrint(Print* pr, const __FlashStringHelper* msg);
+
   /** Diagnostic call to initialize FatFileSystem - use for
   /** Diagnostic call to initialize FatFileSystem - use for
    *  diagnostic purposes only.
    *  diagnostic purposes only.
    *  \return true for success else false.
    *  \return true for success else false.
@@ -183,18 +163,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    * \param[in] msg Message to print.
    */
    */
   void initErrorHalt(Print* pr, char const *msg);
   void initErrorHalt(Print* pr, char const *msg);
-  /**Print message, error details, and halt after SdFat::init() fails.
-    *
-    * \param[in] msg Message to print.
-    */
-  void initErrorHalt(const __FlashStringHelper* msg) {
-    initErrorHalt(&Serial, msg);
-  }
-  /**Print message, error details, and halt after SdFatBase::init() fails.
-   * \param[in] pr Print device for message.
-   * \param[in] msg Message to print.
-   */
-  void initErrorHalt(Print* pr, const __FlashStringHelper* msg);
+
   /** Print error details after SdFat::init() fails. */
   /** Print error details after SdFat::init() fails. */
   void initErrorPrint() {
   void initErrorPrint() {
     initErrorPrint(&Serial);
     initErrorPrint(&Serial);
@@ -217,6 +186,45 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    * \param[in] msg Message to print.
    */
    */
   void initErrorPrint(Print* pr, char const *msg);
   void initErrorPrint(Print* pr, char const *msg);
+#if defined(ARDUINO) || defined(DOXYGEN)
+  /** %Print msg, any SD error code, and halt.
+   *
+   * \param[in] msg Message to print.
+   */
+  void errorHalt(const __FlashStringHelper* msg) {
+    errorHalt(&Serial, msg);
+  }
+  /** %Print msg, any SD error code, and halt.
+   *
+   * \param[in] pr Print destination.
+   * \param[in] msg Message to print.
+   */
+  void errorHalt(Print* pr, const __FlashStringHelper* msg);
+  /** %Print msg, any SD error code.
+   *
+   * \param[in] msg Message to print.
+   */
+  void errorPrint(const __FlashStringHelper* msg) {
+    errorPrint(&Serial, msg);
+  }
+  /** %Print msg, any SD error code.
+   *
+   * \param[in] pr Print destination.
+   * \param[in] msg Message to print.
+   */
+  void errorPrint(Print* pr, const __FlashStringHelper* msg);
+  /**Print message, error details, and halt after SdFat::init() fails.
+    *
+    * \param[in] msg Message to print.
+    */
+  void initErrorHalt(const __FlashStringHelper* msg) {
+    initErrorHalt(&Serial, msg);
+  }
+  /**Print message, error details, and halt after SdFatBase::init() fails.
+   * \param[in] pr Print device for message.
+   * \param[in] msg Message to print.
+   */
+  void initErrorHalt(Print* pr, const __FlashStringHelper* msg);
   /**Print message and error details and halt after SdFat::init() fails.
   /**Print message and error details and halt after SdFat::init() fails.
    *
    *
    * \param[in] msg Message to print.
    * \param[in] msg Message to print.
@@ -230,6 +238,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    * \param[in] msg Message to print.
    */
    */
   void initErrorPrint(Print* pr, const __FlashStringHelper* msg);
   void initErrorPrint(Print* pr, const __FlashStringHelper* msg);
+#endif  // defined(ARDUINO) || defined(DOXYGEN)
 
 
  private:
  private:
   uint8_t cardErrorCode() {
   uint8_t cardErrorCode() {
@@ -259,6 +268,15 @@ class SdFatBase : public FatFileSystem {
  */
  */
 class SdFat : public SdFatBase {
 class SdFat : public SdFatBase {
  public:
  public:
+#if IMPLEMENT_SPI_INTERFACE_SELECTION
+  SdFat() {
+    m_spi.setSpiIf(0);
+  }
+  explicit SdFat(uint8_t spiIf) {
+    m_spi.setSpiIf(spiIf < SPI_INTERFACE_COUNT ? spiIf : 0);
+  }
+#endif  // IMPLEMENT_SPI_INTERFACE_SELECTION
+
   /** Initialize SD card and file system.
   /** Initialize SD card and file system.
    *
    *
    * \param[in] csPin SD card chip select pin.
    * \param[in] csPin SD card chip select pin.
@@ -276,6 +294,7 @@ class SdFat : public SdFatBase {
   bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) {
   bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) {
     return card()->begin(&m_spi, csPin, divisor);
     return card()->begin(&m_spi, csPin, divisor);
   }
   }
+
  private:
  private:
   SpiDefault_t m_spi;
   SpiDefault_t m_spi;
 };
 };

+ 67 - 15
SdFat/SdFatConfig.h → SdFat/src/SdFatConfig.h

@@ -63,7 +63,8 @@
  * The symbol SD_SPI_CONFIGURATION defines SPI access to the SD card.
  * The symbol SD_SPI_CONFIGURATION defines SPI access to the SD card.
  *
  *
  * IF SD_SPI_CONFIGUTATION is define to be zero, only the SdFat class
  * IF SD_SPI_CONFIGUTATION is define to be zero, only the SdFat class
- * is define and SdFat uses a fast custom SPI implementation.
+ * is define and SdFat uses a fast custom SPI implementation if avaiable.
+ * If SD_HAS_CUSTOM_SPI is zero, the standard SPI library is used.
  *
  *
  * If SD_SPI_CONFIGURATION is define to be one, only the SdFat class is
  * If SD_SPI_CONFIGURATION is define to be one, only the SdFat class is
  * define and SdFat uses the standard Arduino SPI.h library.
  * define and SdFat uses the standard Arduino SPI.h library.
@@ -93,34 +94,43 @@ uint8_t const SOFT_SPI_MISO_PIN = 12;
 /** Software SPI Clock pin */
 /** Software SPI Clock pin */
 uint8_t const SOFT_SPI_SCK_PIN = 13;
 uint8_t const SOFT_SPI_SCK_PIN = 13;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+/** 
+ * Set MAINTAIN_FREE_CLUSTER_COUNT nonzero to keep the count of free clusters
+ * updated.  This will increase the speed of the freeClusterCount() call
+ * after the first call.  Extra flash will be required.
+ */
+#define MAINTAIN_FREE_CLUSTER_COUNT 0
+//------------------------------------------------------------------------------
 /**
 /**
  * To enable SD card CRC checking set USE_SD_CRC nonzero.
  * To enable SD card CRC checking set USE_SD_CRC nonzero.
  *
  *
- * Set USE_SD_CRC to 1 to use a smaller slower CRC-CCITT function.
+ * Set USE_SD_CRC to 1 to use a smaller CRC-CCITT function.  This function
+ * is slower for AVR but may be fast for ARM and other processors.
  *
  *
- * Set USE_SD_CRC to 2 to used a larger faster table driven CRC-CCITT function.
+ * Set USE_SD_CRC to 2 to used a larger table driven CRC-CCITT function.  This
+ * function is faster for AVR but may be slower for ARM and other processors.
  */
  */
 #define USE_SD_CRC 0
 #define USE_SD_CRC 0
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /**
 /**
- * Set ENABLE_SPI_TRANSACTION nonzero to enable the SPI transaction feature
+ * Set ENABLE_SPI_TRANSACTIONS nonzero to enable the SPI transaction feature
  * of the standard Arduino SPI library.  You must include SPI.h in your
  * of the standard Arduino SPI library.  You must include SPI.h in your
- * programs when ENABLE_SPI_TRANSACTION is nonzero.
+ * programs when ENABLE_SPI_TRANSACTIONS is nonzero.
  */
  */
-#define ENABLE_SPI_TRANSACTION 0
+#define ENABLE_SPI_TRANSACTIONS 0
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /**
 /**
- * Set ENABLE_SPI_YIELD nonzero to enable release of the SPI bus during
- * SD card busy waits.
+ * Handle Watchdog Timer for WiFi modules.
  *
  *
- * This will allow interrupt routines to access the SPI bus if
- * ENABLE_SPI_TRANSACTION is nonzero.
- *
- * Setting ENABLE_SPI_YIELD will introduce some extra overhead and will
- * slightly slow transfer rates.  A few older SD cards may fail when
- * ENABLE_SPI_YIELD is nonzero.
+ * Yield will be called before accessing the SPI bus if it has been more
+ * than WDT_YIELD_TIME_MICROS microseconds since the last yield call by SdFat.
  */
  */
-#define ENABLE_SPI_YIELD 0
+#if defined(PLATFORM_ID) || defined(ESP8266)
+// If Particle device or ESP8266 call yield.
+#define WDT_YIELD_TIME_MICROS 100000
+#else
+#define WDT_YIELD_TIME_MICROS 0
+#endif
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /**
 /**
  * Set FAT12_SUPPORT nonzero to enable use if FAT12 volumes.
  * Set FAT12_SUPPORT nonzero to enable use if FAT12 volumes.
@@ -185,4 +195,46 @@ const uint8_t SPI_SCK_INIT_DIVISOR = 128;
 #else  // RAMEND
 #else  // RAMEND
 #define USE_MULTI_BLOCK_IO 1
 #define USE_MULTI_BLOCK_IO 1
 #endif  // RAMEND
 #endif  // RAMEND
+//------------------------------------------------------------------------------
+/**
+ * Determine the default SPI configuration.
+ */
+#if defined(__AVR__)\
+  || defined(__SAM3X8E__) || defined(__SAM3X8H__)\
+  || (defined(__arm__) && defined(CORE_TEENSY))\
+  || defined(__STM32F1__)\
+  || defined(PLATFORM_ID)\
+  || defined(ESP8266)\
+  || defined(DOXYGEN)
+// Use custom fast implementation.
+#define SD_HAS_CUSTOM_SPI 1
+#else  // SD_HAS_CUSTOM_SPI
+// Use standard SPI library.
+#define SD_HAS_CUSTOM_SPI 0
+#endif  // SD_HAS_CUSTOM_SPI
+//-----------------------------------------------------------------------------
+/**
+ *  Number of hardware interfaces.
+ */
+#if defined(PLATFORM_ID)
+#if Wiring_SPI1 && Wiring_SPI2
+#define SPI_INTERFACE_COUNT 3
+#elif Wiring_SPI1
+#define SPI_INTERFACE_COUNT 2
+#endif  // Wiring_SPI1 && Wiring_SPI2
+#endif  // defined(PLATFORM_ID)
+// default is one
+#ifndef SPI_INTERFACE_COUNT
+#define SPI_INTERFACE_COUNT 1
+#endif  // SPI_INTERFACE_COUNT
+//------------------------------------------------------------------------------
+/**
+ * Check if API to select HW SPI interface is needed.
+ */
+#if SPI_INTERFACE_COUNT > 1 && SD_HAS_CUSTOM_SPI\
+  && SD_SPI_CONFIGURATION != 1 && SD_SPI_CONFIGURATION != 2
+#define IMPLEMENT_SPI_INTERFACE_SELECTION 1
+#else  // SPI_INTERFACE_COUNT > 1
+#define IMPLEMENT_SPI_INTERFACE_SELECTION 0
+#endif  // SPI_INTERFACE_COUNT > 1
 #endif  // SdFatConfig_h
 #endif  // SdFatConfig_h

+ 2 - 12
SdFat/SdFatUtil.cpp → SdFat/src/SdFatUtil.cpp

@@ -1,5 +1,5 @@
 /* Arduino SdFat Library
 /* Arduino SdFat Library
- * Copyright (C) 2012 by William Greiman
+ * Copyright (C) 2015 by William Greiman
  *
  *
  * This file is part of the Arduino SdFat Library
  * This file is part of the Arduino SdFat Library
  *
  *
@@ -38,14 +38,4 @@ int SdFatUtil::FreeRam() {
   return __brkval ? &top - __brkval : &top - &__bss_end;
   return __brkval ? &top - __brkval : &top - &__bss_end;
 }
 }
 #endif  // __arm
 #endif  // __arm
-//------------------------------------------------------------------------------
-void SdFatUtil::print_P(Print* pr, PGM_P str) {
-  for (uint8_t c; (c = pgm_read_byte(str)); str++) {
-    pr->write(c);
-  }
-}
-//------------------------------------------------------------------------------
-void SdFatUtil::println_P(Print* pr, PGM_P str) {
-  print_P(pr, str);
-  pr->println();
-}
+

+ 35 - 0
SdFat/src/SdFatUtil.h

@@ -0,0 +1,35 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2012 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#ifndef SdFatUtil_h
+#define SdFatUtil_h
+/**
+ * \file
+ * \brief Useful utility functions.
+ */
+#include "SdFat.h"
+
+namespace SdFatUtil {
+  /** Amount of free RAM
+   * \return The number of free bytes.
+   */
+  int FreeRam();
+}  // namespace SdFatUtil
+using namespace SdFatUtil;  // NOLINT
+#endif  // #define SdFatUtil_h

+ 378 - 0
SdFat/src/SdSpiCard/DigitalPin.h

@@ -0,0 +1,378 @@
+/* Arduino DigitalIO Library
+ * Copyright (C) 2013 by William Greiman
+ *
+ * This file is part of the Arduino DigitalIO Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino DigitalIO Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+/**
+ * @file
+ * @brief Fast Digital Pin functions
+ *
+ * @defgroup digitalPin Fast Pin I/O
+ * @details  Fast Digital I/O functions and template class.
+ * @{
+ */
+#ifndef DigitalPin_h
+#define DigitalPin_h
+#include "SystemInclude.h"
+#if defined(__AVR__)  || defined(DOXYGEN)
+#include <avr/io.h>
+/** GpioPinMap type */
+struct GpioPinMap_t {
+  volatile uint8_t* pin;   /**< address of PIN for this pin */
+  volatile uint8_t* ddr;   /**< address of DDR for this pin */
+  volatile uint8_t* port;  /**< address of PORT for this pin */
+  uint8_t mask;            /**< bit mask for this pin */
+};
+
+/** Initializer macro. */
+#define GPIO_PIN(reg, bit) {&PIN##reg, &DDR##reg, &PORT##reg, 1 << bit}
+
+// Include pin map for current board.
+#include "boards/GpioPinMap.h"
+//------------------------------------------------------------------------------
+/** generate bad pin number error */
+void badPinNumber(void)
+  __attribute__((error("Pin number is too large or not a constant")));
+//------------------------------------------------------------------------------
+/** Check for valid pin number
+ * @param[in] pin Number of pin to be checked.
+ */
+static inline __attribute__((always_inline))
+void badPinCheck(uint8_t pin) {
+  if (!__builtin_constant_p(pin) || pin >= NUM_DIGITAL_PINS) {
+     badPinNumber();
+  }
+}
+//------------------------------------------------------------------------------
+/** DDR register address
+ * @param[in] pin Arduino pin number
+ * @return register address
+ */
+static inline __attribute__((always_inline))
+volatile uint8_t* ddrReg(uint8_t pin) {
+  badPinCheck(pin);
+  return GpioPinMap[pin].ddr;
+}
+//------------------------------------------------------------------------------
+/** Bit mask for pin
+ * @param[in] pin Arduino pin number
+ * @return mask
+ */
+static inline __attribute__((always_inline))
+uint8_t pinMask(uint8_t pin) {
+  badPinCheck(pin);
+  return GpioPinMap[pin].mask;
+}
+//------------------------------------------------------------------------------
+/** PIN register address
+ * @param[in] pin Arduino pin number
+ * @return register address
+ */
+static inline __attribute__((always_inline))
+volatile uint8_t* pinReg(uint8_t pin) {
+  badPinCheck(pin);
+  return GpioPinMap[pin].pin;
+}
+//------------------------------------------------------------------------------
+/** PORT register address
+ * @param[in] pin Arduino pin number
+ * @return register address
+ */
+static inline __attribute__((always_inline))
+volatile uint8_t* portReg(uint8_t pin) {
+  badPinCheck(pin);
+  return GpioPinMap[pin].port;
+}
+//------------------------------------------------------------------------------
+/** Fast write helper.
+ * @param[in] address I/O register address
+ * @param[in] mask bit mask for pin
+ * @param[in] level value for bit
+ */
+static inline __attribute__((always_inline))
+void fastBitWriteSafe(volatile uint8_t* address, uint8_t mask, bool level) {
+  uint8_t s;
+  if (address > reinterpret_cast<uint8_t*>(0X3F)) {
+    s = SREG;
+    cli();
+  }
+  if (level) {
+    *address |= mask;
+  } else {
+    *address &= ~mask;
+  }
+  if (address > reinterpret_cast<uint8_t*>(0X3F)) {
+    SREG = s;
+  }
+}
+//------------------------------------------------------------------------------
+/** Read pin value.
+ * @param[in] pin Arduino pin number
+ * @return value read
+ */
+static inline __attribute__((always_inline))
+bool fastDigitalRead(uint8_t pin) {
+  return *pinReg(pin) & pinMask(pin);
+}
+//------------------------------------------------------------------------------
+/** Toggle a pin.
+ * @param[in] pin Arduino pin number
+ *
+ * If the pin is in output mode toggle the pin level.
+ * If the pin is in input mode toggle the state of the 20K pullup.
+ */
+static inline __attribute__((always_inline))
+void fastDigitalToggle(uint8_t pin) {
+    if (pinReg(pin) > reinterpret_cast<uint8_t*>(0X3F)) {
+      // must write bit to high address port
+      *pinReg(pin) = pinMask(pin);
+    } else {
+      // will compile to sbi and PIN register will not be read.
+      *pinReg(pin) |= pinMask(pin);
+    }
+}
+//------------------------------------------------------------------------------
+/** Set pin value.
+ * @param[in] pin Arduino pin number
+ * @param[in] level value to write
+ */
+static inline __attribute__((always_inline))
+void fastDigitalWrite(uint8_t pin, bool level) {
+  fastBitWriteSafe(portReg(pin), pinMask(pin), level);
+}
+//------------------------------------------------------------------------------
+/** Write the DDR register.
+ * @param[in] pin Arduino pin number
+ * @param[in] level value to write
+ */
+static inline __attribute__((always_inline))
+void fastDdrWrite(uint8_t pin, bool level) {
+  fastBitWriteSafe(ddrReg(pin), pinMask(pin), level);
+}
+//------------------------------------------------------------------------------
+/** Set pin mode.
+ * @param[in] pin Arduino pin number
+ * @param[in] mode INPUT, OUTPUT, or INPUT_PULLUP.
+ *
+ * The internal pullup resistors will be enabled if mode is INPUT_PULLUP
+ * and disabled if the mode is INPUT.
+ */
+static inline __attribute__((always_inline))
+void fastPinMode(uint8_t pin, uint8_t mode) {
+  fastDdrWrite(pin, mode == OUTPUT);
+  if (mode != OUTPUT) {
+    fastDigitalWrite(pin, mode == INPUT_PULLUP);
+  }
+}
+#else  // defined(__AVR__)
+#if defined(CORE_TEENSY)
+//------------------------------------------------------------------------------
+/** read pin value
+ * @param[in] pin Arduino pin number
+ * @return value read
+ */
+static inline __attribute__((always_inline))
+bool fastDigitalRead(uint8_t pin) {
+  return *portInputRegister(pin);
+}
+//------------------------------------------------------------------------------
+/** Set pin value
+ * @param[in] pin Arduino pin number
+ * @param[in] level value to write
+ */
+static inline __attribute__((always_inline))
+void fastDigitalWrite(uint8_t pin, bool value) {
+  if (value) {
+    *portSetRegister(pin) = 1;
+  } else {
+    *portClearRegister(pin) = 1;
+  }
+}
+#elif defined(__SAM3X8E__) || defined(__SAM3X8H__)
+//------------------------------------------------------------------------------
+/** read pin value
+ * @param[in] pin Arduino pin number
+ * @return value read
+ */
+static inline __attribute__((always_inline))
+bool fastDigitalRead(uint8_t pin) {
+  return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin;
+}
+//------------------------------------------------------------------------------
+/** Set pin value
+ * @param[in] pin Arduino pin number
+ * @param[in] level value to write
+ */
+static inline __attribute__((always_inline))
+void fastDigitalWrite(uint8_t pin, bool value) {
+  if (value) {
+    g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin;
+  } else {
+    g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin;
+  }
+}
+#elif defined(ESP8266)
+//------------------------------------------------------------------------------
+/** Set pin value
+ * @param[in] pin Arduino pin number
+ * @param[in] val value to write
+ */
+static inline __attribute__((always_inline))
+void fastDigitalWrite(uint8_t pin, uint8_t val) {
+  if (pin < 16) {
+    if (val) {
+      GPOS = (1 << pin);
+    } else {
+      GPOC = (1 << pin);
+    }
+  } else if (pin == 16) {
+    if (val) {
+      GP16O |= 1;
+    } else {
+      GP16O &= ~1;
+    }
+  }
+}
+//------------------------------------------------------------------------------
+/** Read pin value
+ * @param[in] pin Arduino pin number
+ * @return value read
+ */
+static inline __attribute__((always_inline))
+bool fastDigitalRead(uint8_t pin) {
+  if (pin < 16) {
+    return GPIP(pin);
+  } else if (pin == 16) {
+    return GP16I & 0x01;
+  }
+  return 0;
+}
+#else  // CORE_TEENSY
+//------------------------------------------------------------------------------
+inline void fastDigitalWrite(uint8_t pin, bool value) {
+  digitalWrite(pin, value);
+}
+//------------------------------------------------------------------------------
+inline bool fastDigitalRead(uint8_t pin) {return digitalRead(pin);}
+#endif  // CORE_TEENSY
+//------------------------------------------------------------------------------
+inline void fastDigitalToggle(uint8_t pin) {
+  fastDigitalWrite(pin, !fastDigitalRead(pin));
+}
+//------------------------------------------------------------------------------
+#define fastPinMode(pin, mode) pinMode(pin, mode)
+#endif  // __AVR__
+//------------------------------------------------------------------------------
+/** set pin configuration
+ * @param[in] pin Arduino pin number
+ * @param[in] mode mode INPUT or OUTPUT.
+ * @param[in] level If mode is output, set level high/low.
+ *                  If mode is input, enable or disable the pin's 20K pullup.
+ */
+#define fastPinConfig(pin, mode, level)\
+  {fastPinMode(pin, mode); fastDigitalWrite(pin, level);}
+//==============================================================================
+/**
+ * @class DigitalPin
+ * @brief Fast digital port I/O
+ */
+template<uint8_t PinNumber>
+class DigitalPin {
+ public:
+  //----------------------------------------------------------------------------
+  /** Constructor */
+  DigitalPin() {}
+  //----------------------------------------------------------------------------
+  /** Asignment operator.
+   * @param[in] value If true set the pin's level high else set the
+   *  pin's level low.
+   *
+   * @return This DigitalPin instance.
+   */
+  inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
+    write(value);
+    return *this;
+  }
+  //----------------------------------------------------------------------------
+  /** Parenthesis operator.
+   * @return Pin's level
+   */
+  inline operator bool () const __attribute__((always_inline)) {
+    return read();
+  }
+  //----------------------------------------------------------------------------
+  /** Set pin configuration.
+   * @param[in] mode: INPUT or OUTPUT.
+   * @param[in] level If mode is OUTPUT, set level high/low.
+   *                  If mode is INPUT, enable or disable the pin's 20K pullup.
+   */
+  inline __attribute__((always_inline))
+  void config(uint8_t mode, bool level) {
+    fastPinConfig(PinNumber, mode, level);
+  }
+  //----------------------------------------------------------------------------
+  /**
+   * Set pin level high if output mode or enable 20K pullup if input mode.
+   */
+  inline __attribute__((always_inline))
+  void high() {write(true);}
+  //----------------------------------------------------------------------------
+  /**
+   * Set pin level low if output mode or disable 20K pullup if input mode.
+   */
+  inline __attribute__((always_inline))
+  void low() {write(false);}
+  //----------------------------------------------------------------------------
+  /**
+   * Set pin mode.
+   * @param[in] mode: INPUT, OUTPUT, or INPUT_PULLUP.
+   *
+   * The internal pullup resistors will be enabled if mode is INPUT_PULLUP
+   * and disabled if the mode is INPUT.
+   */
+  inline __attribute__((always_inline))
+  void mode(uint8_t mode) {
+    fastPinMode(PinNumber, mode);
+  }
+  //----------------------------------------------------------------------------
+  /** @return Pin's level. */
+  inline __attribute__((always_inline))
+  bool read() const {
+    return fastDigitalRead(PinNumber);
+  }
+  //----------------------------------------------------------------------------
+  /** Toggle a pin.
+   *
+   * If the pin is in output mode toggle the pin's level.
+   * If the pin is in input mode toggle the state of the 20K pullup.
+   */
+  inline __attribute__((always_inline))
+  void toggle() {
+    fastDigitalToggle(PinNumber);
+  }
+  //----------------------------------------------------------------------------
+  /** Write the pin's level.
+   * @param[in] value If true set the pin's level high else set the
+   *  pin's level low.
+   */
+  inline __attribute__((always_inline))
+  void write(bool value) {
+    fastDigitalWrite(PinNumber, value);
+  }
+};
+#endif  // DigitalPin_h
+/** @} */

+ 9 - 5
SdFat/SdInfo.h → SdFat/src/SdSpiCard/SdInfo.h

@@ -73,7 +73,7 @@ uint8_t const SD_CARD_ERROR_WRITE = 0X13;
 /** attempt to write protected block zero */
 /** attempt to write protected block zero */
 uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14;  // REMOVE - not used
 uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14;  // REMOVE - not used
 /** card did not go ready for a multiple block write */
 /** card did not go ready for a multiple block write */
-uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X15;
+uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X15;  // Not used
 /** card returned an error to a CMD13 status check after a write */
 /** card returned an error to a CMD13 status check after a write */
 uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16;
 uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16;
 /** timeout occurred during write programming */
 /** timeout occurred during write programming */
@@ -88,6 +88,8 @@ uint8_t const SD_CARD_ERROR_CMD59 = 0X1A;
 uint8_t const SD_CARD_ERROR_READ_CRC = 0X1B;
 uint8_t const SD_CARD_ERROR_READ_CRC = 0X1B;
 /** SPI DMA error */
 /** SPI DMA error */
 uint8_t const SD_CARD_ERROR_SPI_DMA = 0X1C;
 uint8_t const SD_CARD_ERROR_SPI_DMA = 0X1C;
+/** CMD6 not accepted */
+uint8_t const SD_CARD_ERROR_CMD6 = 0X1D;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // card types
 // card types
 /** Standard capacity V1 SD card */
 /** Standard capacity V1 SD card */
@@ -115,17 +117,19 @@ uint8_t const SPI_SIXTEENTH_SPEED = 32;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // SD operation timeouts
 // SD operation timeouts
 /** init timeout ms */
 /** init timeout ms */
-uint16_t const SD_INIT_TIMEOUT = 2000;
+unsigned const SD_INIT_TIMEOUT = 2000;
 /** erase timeout ms */
 /** erase timeout ms */
-uint16_t const SD_ERASE_TIMEOUT = 10000;
+unsigned const SD_ERASE_TIMEOUT = 10000;
 /** read timeout ms */
 /** read timeout ms */
-uint16_t const SD_READ_TIMEOUT = 300;
+unsigned const SD_READ_TIMEOUT = 300;
 /** write time out ms */
 /** write time out ms */
-uint16_t const SD_WRITE_TIMEOUT = 600;
+unsigned const SD_WRITE_TIMEOUT = 600;
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // SD card commands
 // SD card commands
 /** GO_IDLE_STATE - init card in spi mode if CS low */
 /** GO_IDLE_STATE - init card in spi mode if CS low */
 uint8_t const CMD0 = 0X00;
 uint8_t const CMD0 = 0X00;
+/** SWITCH_FUNC - Switch Function Command */
+uint8_t const CMD6 = 0X06;
 /** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
 /** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
 uint8_t const CMD8 = 0X08;
 uint8_t const CMD8 = 0X08;
 /** SEND_CSD - read the Card Specific Data (CSD register) */
 /** SEND_CSD - read the Card Specific Data (CSD register) */

+ 85 - 44
SdFat/SdSpi.h → SdFat/src/SdSpiCard/SdSpi.h

@@ -23,9 +23,8 @@
 */
 */
 #ifndef SdSpi_h
 #ifndef SdSpi_h
 #define SdSpi_h
 #define SdSpi_h
-#include <Arduino.h>
+#include "SystemInclude.h"
 #include "SdFatConfig.h"
 #include "SdFatConfig.h"
-
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /**
 /**
  * \class SdSpiBase
  * \class SdSpiBase
@@ -33,13 +32,20 @@
  */
  */
 class SdSpiBase {
 class SdSpiBase {
  public:
  public:
-  /** Initialize the SPI bus */
-  virtual void begin() = 0;
+  /** Initialize the SPI bus.
+   *
+   * \param[in] chipSelectPin SD card chip select pin.
+   */
+  virtual void begin(uint8_t chipSelectPin) = 0;
   /** Set SPI options for access to SD/SDHC cards.
   /** Set SPI options for access to SD/SDHC cards.
    *
    *
    * \param[in] divisor SCK clock divider relative to the system clock.
    * \param[in] divisor SCK clock divider relative to the system clock.
    */
    */
-  virtual void init(uint8_t divisor);
+  virtual void beginTransaction(uint8_t divisor);
+  /**
+   * End SPI transaction.
+   */
+  virtual void endTransaction();
   /** Receive a byte.
   /** Receive a byte.
    *
    *
    * \return The byte.
    * \return The byte.
@@ -64,8 +70,6 @@ class SdSpiBase {
   * \param[in] n Number of bytes to send.
   * \param[in] n Number of bytes to send.
   */
   */
   virtual void send(const uint8_t* buf, size_t n) = 0;
   virtual void send(const uint8_t* buf, size_t n) = 0;
-  /** \return true if hardware SPI else false */
-  virtual bool useSpiTransactions() = 0;
 };
 };
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /**
 /**
@@ -78,13 +82,20 @@ class SdSpi : public SdSpiBase {
 class SdSpi {
 class SdSpi {
 #endif  // SD_SPI_CONFIGURATION >= 3
 #endif  // SD_SPI_CONFIGURATION >= 3
  public:
  public:
-  /** Initialize the SPI bus */
-  void begin();
+  /** Initialize the SPI bus.
+   *
+   * \param[in] chipSelectPin SD card chip select pin.
+   */
+  void begin(uint8_t chipSelectPin);
   /** Set SPI options for access to SD/SDHC cards.
   /** Set SPI options for access to SD/SDHC cards.
    *
    *
    * \param[in] divisor SCK clock divider relative to the system clock.
    * \param[in] divisor SCK clock divider relative to the system clock.
    */
    */
-  void init(uint8_t divisor);
+  void beginTransaction(uint8_t divisor);
+  /**
+   * End SPI transaction
+   */
+  void endTransaction();
   /** Receive a byte.
   /** Receive a byte.
    *
    *
    * \return The byte.
    * \return The byte.
@@ -110,9 +121,13 @@ class SdSpi {
    */
    */
   void send(const uint8_t* buf, size_t n);
   void send(const uint8_t* buf, size_t n);
   /** \return true - uses SPI transactions */
   /** \return true - uses SPI transactions */
-  bool useSpiTransactions() {
-    return true;
+#if IMPLEMENT_SPI_INTERFACE_SELECTION
+  void setSpiIf(uint8_t spiIf) {
+    m_spiIf = spiIf;
   }
   }
+ private:
+  uint8_t m_spiIf;
+#endif  // IMPLEMENT_SPI_INTERFACE_SELECTION
 };
 };
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /**
 /**
@@ -120,27 +135,32 @@ class SdSpi {
  * \brief Arduino SPI library class for access to SD and SDHC flash
  * \brief Arduino SPI library class for access to SD and SDHC flash
  *        memory cards.
  *        memory cards.
  */
  */
-#if SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1 || defined(DOXYGEN)
-#include <SPI.h>
 #if SD_SPI_CONFIGURATION >= 3
 #if SD_SPI_CONFIGURATION >= 3
 class SdSpiLib : public SdSpiBase {
 class SdSpiLib : public SdSpiBase {
 #else  // SD_SPI_CONFIGURATION >= 3
 #else  // SD_SPI_CONFIGURATION >= 3
 class SdSpiLib {
 class SdSpiLib {
 #endif  // SD_SPI_CONFIGURATION >= 3
 #endif  // SD_SPI_CONFIGURATION >= 3
  public:
  public:
-  /**
-   * Initialize SPI pins.
+  /** Initialize the SPI bus.
+   *
+   * \param[in] chipSelectPin SD card chip select pin.
    */
    */
-  void begin() {
+  void begin(uint8_t chipSelectPin) {
+    pinMode(chipSelectPin, OUTPUT);
+    digitalWrite(chipSelectPin, HIGH);
     SPI.begin();
     SPI.begin();
   }
   }
   /** Set SPI options for access to SD/SDHC cards.
   /** Set SPI options for access to SD/SDHC cards.
    *
    *
    * \param[in] divisor SCK clock divider relative to the system clock.
    * \param[in] divisor SCK clock divider relative to the system clock.
    */
    */
-  void init(uint8_t divisor) {
+  void beginTransaction(uint8_t divisor) {
+#if ENABLE_SPI_TRANSACTIONS
+    SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
+#else  // ENABLE_SPI_TRANSACTIONS
     SPI.setBitOrder(MSBFIRST);
     SPI.setBitOrder(MSBFIRST);
     SPI.setDataMode(SPI_MODE0);
     SPI.setDataMode(SPI_MODE0);
+#endif  // ENABLE_SPI_TRANSACTIONS
 #ifndef SPI_CLOCK_DIV128
 #ifndef SPI_CLOCK_DIV128
     SPI.setClockDivider(divisor);
     SPI.setClockDivider(divisor);
 #else  // SPI_CLOCK_DIV128
 #else  // SPI_CLOCK_DIV128
@@ -162,6 +182,14 @@ class SdSpiLib {
     }
     }
     SPI.setClockDivider(v);
     SPI.setClockDivider(v);
 #endif  // SPI_CLOCK_DIV128
 #endif  // SPI_CLOCK_DIV128
+  }
+  /**
+   * End SPI transaction.
+   */
+  void endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+    SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
   }
   }
   /** Receive a byte.
   /** Receive a byte.
    *
    *
@@ -200,15 +228,14 @@ class SdSpiLib {
       SPI.transfer(buf[i]);
       SPI.transfer(buf[i]);
     }
     }
   }
   }
-  /** \return true - uses SPI transactions */
-  bool useSpiTransactions() {
-    return true;
-  }
 };
 };
-#endif  // SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 #if SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN)
 #if SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN)
-#include "utility/SoftSPI.h"
+#ifdef ARDUINO
+#include "SoftSPI.h"
+#elif defined(PLATFORM_ID)  // Only defined if a Particle device
+#include "SoftSPIParticle.h"
+#endif  // ARDUINO
 /**
 /**
  * \class SdSpiSoft
  * \class SdSpiSoft
  * \brief Software SPI class for access to SD and SDHC flash memory cards.
  * \brief Software SPI class for access to SD and SDHC flash memory cards.
@@ -216,17 +243,26 @@ class SdSpiLib {
 template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
 template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
 class SdSpiSoft : public SdSpiBase {
 class SdSpiSoft : public SdSpiBase {
  public:
  public:
-  /**
-   * initialize SPI pins
+  /** Initialize the SPI bus.
+   *
+   * \param[in] chipSelectPin SD card chip select pin.
    */
    */
-  void begin() {
+  void begin(uint8_t chipSelectPin) {
+    pinMode(chipSelectPin, OUTPUT);
+    digitalWrite(chipSelectPin, HIGH);
     m_spi.begin();
     m_spi.begin();
   }
   }
   /**
   /**
    * Initialize hardware SPI - dummy for soft SPI
    * Initialize hardware SPI - dummy for soft SPI
    * \param[in] divisor SCK divisor - ignored.
    * \param[in] divisor SCK divisor - ignored.
    */
    */
-  void init(uint8_t divisor) {}
+  void beginTransaction(uint8_t divisor) {
+    (void)divisor;
+  }
+  /**
+   * End SPI transaction - dummy for soft SPI
+   */
+  void endTransaction() {}
   /** Receive a byte.
   /** Receive a byte.
    *
    *
    * \return The byte.
    * \return The byte.
@@ -264,34 +300,28 @@ class SdSpiSoft : public SdSpiBase {
       send(buf[i]);
       send(buf[i]);
     }
     }
   }
   }
-  /** \return false - no SPI transactions */
-  bool useSpiTransactions() {
-    return false;
-  }
 
 
  private:
  private:
   SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
   SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
 };
 };
 #endif  // SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN)
 #endif  // SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN)
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-#if SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
-/** Default is custom fast SPI. */
-typedef SdSpi SpiDefault_t;
-#elif SD_SPI_CONFIGURATION == 1
-/** Default is Arduino library SPI. */
-typedef SdSpiLib SpiDefault_t;
-#elif SD_SPI_CONFIGURATION == 2
+#if SD_SPI_CONFIGURATION == 2
 /** Default is software SPI. */
 /** Default is software SPI. */
 typedef SdSpiSoft<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN>
 typedef SdSpiSoft<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN>
 SpiDefault_t;
 SpiDefault_t;
-#else  // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
-#error bad SD_SPI_CONFIGURATION
-#endif  // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
+#elif SD_SPI_CONFIGURATION == 1 || !SD_HAS_CUSTOM_SPI
+/** Default is Arduino library SPI. */
+typedef SdSpiLib SpiDefault_t;
+#else  // SpiDefault_t
+/** Default is custom fast SPI. */
+typedef SdSpi SpiDefault_t;
+#endif  // SpiDefault_t
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // Use of in-line for AVR to save flash.
 // Use of in-line for AVR to save flash.
 #ifdef __AVR__
 #ifdef __AVR__
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-inline void SdSpi::begin() {
+inline void SdSpi::begin(uint8_t chipSelectPin) {
 #ifdef __AVR_ATmega328P__
 #ifdef __AVR_ATmega328P__
   // Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi.
   // Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi.
   PORTB |= 1 << 2;  // SS high
   PORTB |= 1 << 2;  // SS high
@@ -308,9 +338,14 @@ inline void SdSpi::begin() {
   pinMode(MOSI, OUTPUT);
   pinMode(MOSI, OUTPUT);
   pinMode(SCK, OUTPUT);
   pinMode(SCK, OUTPUT);
 #endif  // __AVR_ATmega328P__
 #endif  // __AVR_ATmega328P__
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-inline void SdSpi::init(uint8_t divisor) {
+inline void SdSpi::beginTransaction(uint8_t divisor) {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.beginTransaction(SPISettings());
+#endif  // ENABLE_SPI_TRANSACTIONS
   uint8_t b = 2;
   uint8_t b = 2;
   uint8_t r = 0;
   uint8_t r = 0;
 
 
@@ -320,6 +355,12 @@ inline void SdSpi::init(uint8_t divisor) {
   SPSR = r & 1 ? 0 : 1 << SPI2X;
   SPSR = r & 1 ? 0 : 1 << SPI2X;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+inline void SdSpi::endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
+}
+//------------------------------------------------------------------------------
 inline uint8_t SdSpi::receive() {
 inline uint8_t SdSpi::receive() {
   SPDR = 0XFF;
   SPDR = 0XFF;
   while (!(SPSR & (1 << SPIF))) {}
   while (!(SPSR & (1 << SPIF))) {}

+ 81 - 65
SdFat/SdSpiCard.cpp → SdFat/src/SdSpiCard/SdSpiCard.cpp

@@ -19,12 +19,11 @@
  */
  */
 #include "SdSpiCard.h"
 #include "SdSpiCard.h"
 #include "SdSpi.h"
 #include "SdSpi.h"
-#if ENABLE_SPI_TRANSACTION
-#include <SPI.h>
-#endif  // ENABLE_SPI_TRANSACTION
 // debug trace macro
 // debug trace macro
 #define SD_TRACE(m, b)
 #define SD_TRACE(m, b)
 // #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
 // #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
+#define SD_CS_DBG(m)
+// #define SD_CS_DBG(m) Serial.println(F(m));
 //==============================================================================
 //==============================================================================
 #if USE_SD_CRC
 #if USE_SD_CRC
 // CRC functions
 // CRC functions
@@ -121,25 +120,26 @@ bool SdSpiCard::begin(m_spi_t* spi, uint8_t chipSelectPin, uint8_t sckDivisor) {
   m_spi = spi;
   m_spi = spi;
   m_chipSelectPin = chipSelectPin;
   m_chipSelectPin = chipSelectPin;
   // 16-bit init start time allows over a minute
   // 16-bit init start time allows over a minute
-  uint16_t t0 = (uint16_t)millis();
+  unsigned t0 = (unsigned)millis();
   uint32_t arg;
   uint32_t arg;
 
 
-  pinMode(m_chipSelectPin, OUTPUT);
-  digitalWrite(m_chipSelectPin, HIGH);
-  spiBegin();
+  // initialize SPI bus and chip select pin.
+  spiBegin(m_chipSelectPin);
 
 
-  // set SCK rate for initialization commands
+  // set SCK rate for initialization commands.
   m_sckDivisor = SPI_SCK_INIT_DIVISOR;
   m_sckDivisor = SPI_SCK_INIT_DIVISOR;
-  spiInit(m_sckDivisor);
+
+  // toggle chip select and set slow SPI clock.
+  chipSelectLow();
+  chipSelectHigh();
 
 
   // must supply min of 74 clock cycles with CS high.
   // must supply min of 74 clock cycles with CS high.
   for (uint8_t i = 0; i < 10; i++) {
   for (uint8_t i = 0; i < 10; i++) {
     spiSend(0XFF);
     spiSend(0XFF);
   }
   }
-
   // command to go idle in SPI mode
   // command to go idle in SPI mode
   while (cardCommand(CMD0, 0) != R1_IDLE_STATE) {
   while (cardCommand(CMD0, 0) != R1_IDLE_STATE) {
-    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
+    if (((unsigned)millis() - t0) > SD_INIT_TIMEOUT) {
       error(SD_CARD_ERROR_CMD0);
       error(SD_CARD_ERROR_CMD0);
       goto fail;
       goto fail;
     }
     }
@@ -163,7 +163,7 @@ bool SdSpiCard::begin(m_spi_t* spi, uint8_t chipSelectPin, uint8_t sckDivisor) {
       type(SD_CARD_TYPE_SD2);
       type(SD_CARD_TYPE_SD2);
       break;
       break;
     }
     }
-    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
+    if (((unsigned)millis() - t0) > SD_INIT_TIMEOUT) {
       error(SD_CARD_ERROR_CMD8);
       error(SD_CARD_ERROR_CMD8);
       goto fail;
       goto fail;
     }
     }
@@ -173,7 +173,7 @@ bool SdSpiCard::begin(m_spi_t* spi, uint8_t chipSelectPin, uint8_t sckDivisor) {
 
 
   while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
   while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
     // check for timeout
     // check for timeout
-    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
+    if (((unsigned)millis() - t0) > SD_INIT_TIMEOUT) {
       error(SD_CARD_ERROR_ACMD41);
       error(SD_CARD_ERROR_ACMD41);
       goto fail;
       goto fail;
     }
     }
@@ -204,29 +204,32 @@ fail:
 // send command and return error code.  Return zero for OK
 // send command and return error code.  Return zero for OK
 uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
 uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
   // select card
   // select card
-  chipSelectLow();
-
+  if (!m_selected) {
+    chipSelectLow();
+  }
   // wait if busy
   // wait if busy
   waitNotBusy(SD_WRITE_TIMEOUT);
   waitNotBusy(SD_WRITE_TIMEOUT);
 
 
-  uint8_t *pa = reinterpret_cast<uint8_t *>(&arg);
-
 #if USE_SD_CRC
 #if USE_SD_CRC
   // form message
   // form message
-  uint8_t d[6] = {cmd | 0X40, pa[3], pa[2], pa[1], pa[0]};
+  uint8_t buf[6];
+  buf[0] = (uint8_t)0x40U | cmd;
+  buf[1] = (uint8_t)(arg >> 24U);
+  buf[2] = (uint8_t)(arg >> 16U);
+  buf[3] = (uint8_t)(arg >> 8U);
+  buf[4] = (uint8_t)arg;
 
 
-  // add crc
-  d[5] = CRC7(d, 5);
+  // add CRC
+  buf[5] = CRC7(buf, 5);
 
 
   // send message
   // send message
-  for (uint8_t k = 0; k < 6; k++) {
-    spiSend(d[k]);
-  }
+  spiSend(buf, 6);
 #else  // USE_SD_CRC
 #else  // USE_SD_CRC
   // send command
   // send command
   spiSend(cmd | 0x40);
   spiSend(cmd | 0x40);
 
 
   // send argument
   // send argument
+  uint8_t *pa = reinterpret_cast<uint8_t *>(&arg);
   for (int8_t i = 3; i >= 0; i--) {
   for (int8_t i = 3; i >= 0; i--) {
     spiSend(pa[i]);
     spiSend(pa[i]);
   }
   }
@@ -268,32 +271,33 @@ uint32_t SdSpiCard::cardSize() {
   }
   }
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-void SdSpiCard::spiYield() {
-#if ENABLE_SPI_TRANSACTION && ENABLE_SPI_YIELD && defined(SPI_HAS_TRANSACTION)
-  chipSelectHigh();
-  chipSelectLow();
-#endif  // ENABLE_SPI_TRANSACTION && ENABLE_SPI_YIELD && SPI_HAS_TRANSACTION
-}
-//------------------------------------------------------------------------------
 void SdSpiCard::chipSelectHigh() {
 void SdSpiCard::chipSelectHigh() {
+  if (!m_selected) {
+    SD_CS_DBG("chipSelectHigh error");
+    return;
+  }
   digitalWrite(m_chipSelectPin, HIGH);
   digitalWrite(m_chipSelectPin, HIGH);
   // insure MISO goes high impedance
   // insure MISO goes high impedance
   spiSend(0XFF);
   spiSend(0XFF);
-#if ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION)
-  if (useSpiTransactions()) {
-    SPI.endTransaction();
-  }
-#endif  // ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION)
+  spiEndTransaction();
+  m_selected = false;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 void SdSpiCard::chipSelectLow() {
 void SdSpiCard::chipSelectLow() {
-#if ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION)
-  if (useSpiTransactions()) {
-    SPI.beginTransaction(SPISettings());
-  }
-#endif  // ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION)
-  spiInit(m_sckDivisor);
+#if WDT_YIELD_TIME_MICROS
+  static uint32_t last;
+  if ((micros() - last) > WDT_YIELD_TIME_MICROS) {
+    SysCall::yield();
+    last = micros();
+  }
+#endif  // WDT_YIELD_TIME_MICROS
+  if (m_selected) {
+    SD_CS_DBG("chipSelectLow error");
+    return;
+  }
+  spiBeginTransaction(m_sckDivisor);
   digitalWrite(m_chipSelectPin, LOW);
   digitalWrite(m_chipSelectPin, LOW);
+  m_selected = true;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) {
 bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) {
@@ -339,15 +343,20 @@ bool SdSpiCard::eraseSingleBlockEnable() {
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool SdSpiCard::isBusy() {
 bool SdSpiCard::isBusy() {
-  bool rtn;
-  chipSelectLow();
+  bool rtn = true;
+  bool selected = m_selected;
+  if (!selected) {    
+    chipSelectLow();
+  }
   for (uint8_t i = 0; i < 8; i++) {
   for (uint8_t i = 0; i < 8; i++) {
-    rtn = spiReceive() != 0XFF;
-    if (!rtn) {
+    if (0XFF == spiReceive()) {
+      rtn = false;
       break;
       break;
     }
     }
   }
   }
-  chipSelectHigh();
+  if (!selected) {
+    chipSelectHigh();
+  }
   return rtn;
   return rtn;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -361,7 +370,11 @@ bool SdSpiCard::readBlock(uint32_t blockNumber, uint8_t* dst) {
     error(SD_CARD_ERROR_CMD17);
     error(SD_CARD_ERROR_CMD17);
     goto fail;
     goto fail;
   }
   }
-  return readData(dst, 512);
+  if (!readData(dst, 512)) {
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
 
 
 fail:
 fail:
   chipSelectHigh();
   chipSelectHigh();
@@ -373,7 +386,7 @@ bool SdSpiCard::readBlocks(uint32_t block, uint8_t* dst, size_t count) {
     return false;
     return false;
   }
   }
   for (uint16_t b = 0; b < count; b++, dst += 512) {
   for (uint16_t b = 0; b < count; b++, dst += 512) {
-    if (!readData(dst)) {
+    if (!readData(dst, 512)) {
       return false;
       return false;
     }
     }
   }
   }
@@ -381,8 +394,10 @@ bool SdSpiCard::readBlocks(uint32_t block, uint8_t* dst, size_t count) {
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool SdSpiCard::readData(uint8_t *dst) {
 bool SdSpiCard::readData(uint8_t *dst) {
-  chipSelectLow();
-  return readData(dst, 512);
+  if (!readData(dst, 512)) {
+    return false;
+  }
+  return true;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool SdSpiCard::readData(uint8_t* dst, size_t count) {
 bool SdSpiCard::readData(uint8_t* dst, size_t count) {
@@ -390,9 +405,9 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
   uint16_t crc;
   uint16_t crc;
 #endif  // USE_SD_CRC
 #endif  // USE_SD_CRC
   // wait for start block token
   // wait for start block token
-  uint16_t t0 = millis();
+  unsigned t0 = millis();
   while ((m_status = spiReceive()) == 0XFF) {
   while ((m_status = spiReceive()) == 0XFF) {
-    if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
+    if (((unsigned)millis() - t0) > SD_READ_TIMEOUT) {
       error(SD_CARD_ERROR_READ_TIMEOUT);
       error(SD_CARD_ERROR_READ_TIMEOUT);
       goto fail;
       goto fail;
     }
     }
@@ -419,7 +434,6 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
   spiReceive();
   spiReceive();
   spiReceive();
   spiReceive();
 #endif  // USE_SD_CRC
 #endif  // USE_SD_CRC
-  chipSelectHigh();
   return true;
   return true;
 
 
 fail:
 fail:
@@ -452,7 +466,11 @@ bool SdSpiCard::readRegister(uint8_t cmd, void* buf) {
     error(SD_CARD_ERROR_READ_REG);
     error(SD_CARD_ERROR_READ_REG);
     goto fail;
     goto fail;
   }
   }
-  return readData(dst, 16);
+  if (!readData(dst, 16)) {
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
 
 
 fail:
 fail:
   chipSelectHigh();
   chipSelectHigh();
@@ -468,7 +486,6 @@ bool SdSpiCard::readStart(uint32_t blockNumber) {
     error(SD_CARD_ERROR_CMD18);
     error(SD_CARD_ERROR_CMD18);
     goto fail;
     goto fail;
   }
   }
-  chipSelectHigh();
   return true;
   return true;
 
 
 fail:
 fail:
@@ -491,12 +508,11 @@ fail:
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // wait for card to go not busy
 // wait for card to go not busy
 bool SdSpiCard::waitNotBusy(uint16_t timeoutMillis) {
 bool SdSpiCard::waitNotBusy(uint16_t timeoutMillis) {
-  uint16_t t0 = millis();
+  unsigned t0 = millis();
   while (spiReceive() != 0XFF) {
   while (spiReceive() != 0XFF) {
-    if (((uint16_t)millis() - t0) >= timeoutMillis) {
+    if (((unsigned)millis() - t0) >= timeoutMillis) {
       goto fail;
       goto fail;
     }
     }
-    spiYield();
   }
   }
   return true;
   return true;
 
 
@@ -542,30 +558,32 @@ fail:
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool SdSpiCard::writeBlocks(uint32_t block, const uint8_t* src, size_t count) {
 bool SdSpiCard::writeBlocks(uint32_t block, const uint8_t* src, size_t count) {
   if (!writeStart(block, count)) {
   if (!writeStart(block, count)) {
-    return false;
+    goto fail;
   }
   }
   for (size_t b = 0; b < count; b++, src += 512) {
   for (size_t b = 0; b < count; b++, src += 512) {
     if (!writeData(src)) {
     if (!writeData(src)) {
-      return false;
+      goto fail;
     }
     }
   }
   }
   return writeStop();
   return writeStop();
+
+ fail:
+  chipSelectHigh();
+  return false;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool SdSpiCard::writeData(const uint8_t* src) {
 bool SdSpiCard::writeData(const uint8_t* src) {
-  chipSelectLow();
   // wait for previous write to finish
   // wait for previous write to finish
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
+    error(SD_CARD_ERROR_WRITE_TIMEOUT);
     goto fail;
     goto fail;
   }
   }
   if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
   if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
     goto fail;
     goto fail;
   }
   }
-  chipSelectHigh();
   return true;
   return true;
 
 
 fail:
 fail:
-  error(SD_CARD_ERROR_WRITE_MULTIPLE);
   chipSelectHigh();
   chipSelectHigh();
   return false;
   return false;
 }
 }
@@ -609,7 +627,6 @@ bool SdSpiCard::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
     error(SD_CARD_ERROR_CMD25);
     error(SD_CARD_ERROR_CMD25);
     goto fail;
     goto fail;
   }
   }
-  chipSelectHigh();
   return true;
   return true;
 
 
 fail:
 fail:
@@ -618,7 +635,6 @@ fail:
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 bool SdSpiCard::writeStop() {
 bool SdSpiCard::writeStop() {
-  chipSelectLow();
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
     goto fail;
     goto fail;
   }
   }

+ 37 - 16
SdFat/SdSpiCard.h → SdFat/src/SdSpiCard/SdSpiCard.h

@@ -23,10 +23,10 @@
  * \file
  * \file
  * \brief SdSpiCard class for V2 SD/SDHC cards
  * \brief SdSpiCard class for V2 SD/SDHC cards
  */
  */
-#include <Arduino.h>
-#include <SdFatConfig.h>
-#include <SdInfo.h>
-#include <SdSpi.h>
+#include "SystemInclude.h"
+#include "SdFatConfig.h"
+#include "SdInfo.h"
+#include "SdSpi.h"
 //==============================================================================
 //==============================================================================
 /**
 /**
  * \class SdSpiCard
  * \class SdSpiCard
@@ -41,7 +41,8 @@ class SdSpiCard {
   typedef SdSpiBase m_spi_t;
   typedef SdSpiBase m_spi_t;
 #endif  // SD_SPI_CONFIGURATION < 3
 #endif  // SD_SPI_CONFIGURATION < 3
   /** Construct an instance of SdSpiCard. */
   /** Construct an instance of SdSpiCard. */
-  SdSpiCard() : m_errorCode(SD_CARD_ERROR_INIT_NOT_CALLED), m_type(0) {}
+  SdSpiCard() : m_selected(false),
+                m_errorCode(SD_CARD_ERROR_INIT_NOT_CALLED), m_type(0) {}
   /** Initialize the SD card.
   /** Initialize the SD card.
    * \param[in] spi SPI object.
    * \param[in] spi SPI object.
    * \param[in] chipSelectPin SD chip select pin.
    * \param[in] chipSelectPin SD chip select pin.
@@ -57,6 +58,16 @@ class SdSpiCard {
    *         or zero if an error occurs.
    *         or zero if an error occurs.
    */
    */
   uint32_t cardSize();
   uint32_t cardSize();
+  /** Set the SD chip select pin high, send a dummy byte, and call SPI endTransaction.
+   *
+   * This function should only be called by programs doing raw I/O to the SD.
+   */
+  void chipSelectHigh();
+  /** Set the SD chip select pin low and call SPI beginTransaction.
+   *
+   * This function should only be called by programs doing raw I/O to the SD.
+   */  
+  void chipSelectLow();
   /** Erase a range of blocks.
   /** Erase a range of blocks.
    *
    *
    * \param[in] firstBlock The address of the first block in the range.
    * \param[in] firstBlock The address of the first block in the range.
@@ -180,6 +191,14 @@ class SdSpiCard {
   uint8_t sckDivisor() {
   uint8_t sckDivisor() {
     return m_sckDivisor;
     return m_sckDivisor;
   }
   }
+  /** \return the SD chip select status, true if slected else false. */
+  bool selected() {return m_selected;}
+  /** Set SCK divisor.
+   *  \param[in] sckDivisor value for divisor.
+   */
+  void setSckDivisor(uint8_t sckDivisor) {
+    m_sckDivisor = sckDivisor;
+  }
   /** Return the card type: SD V1, SD V2 or SDHC
   /** Return the card type: SD V1, SD V2 or SDHC
    * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
    * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
    */
    */
@@ -205,7 +224,7 @@ class SdSpiCard {
    * the value false is returned for failure.
    * the value false is returned for failure.
    */
    */
   bool writeBlocks(uint32_t block, const uint8_t* src, size_t count);
   bool writeBlocks(uint32_t block, const uint8_t* src, size_t count);
-  /** Write one data block in a multiple block write sequence
+  /** Write one data block in a multiple block write sequence.
    * \param[in] src Pointer to the location of the data to be written.
    * \param[in] src Pointer to the location of the data to be written.
    * \return The value true is returned for success and
    * \return The value true is returned for success and
    * the value false is returned for failure.
    * the value false is returned for failure.
@@ -239,19 +258,19 @@ class SdSpiCard {
   uint8_t cardCommand(uint8_t cmd, uint32_t arg);
   uint8_t cardCommand(uint8_t cmd, uint32_t arg);
   bool readData(uint8_t* dst, size_t count);
   bool readData(uint8_t* dst, size_t count);
   bool readRegister(uint8_t cmd, void* buf);
   bool readRegister(uint8_t cmd, void* buf);
-  void chipSelectHigh();
-  void chipSelectLow();
-  void spiYield();
   void type(uint8_t value) {
   void type(uint8_t value) {
     m_type = value;
     m_type = value;
   }
   }
   bool waitNotBusy(uint16_t timeoutMillis);
   bool waitNotBusy(uint16_t timeoutMillis);
   bool writeData(uint8_t token, const uint8_t* src);
   bool writeData(uint8_t token, const uint8_t* src);
-  void spiBegin() {
-    m_spi->begin();
+  void spiBegin(uint8_t chipSelectPin) {
+    m_spi->begin(chipSelectPin);
   }
   }
-  void spiInit(uint8_t spiDivisor) {
-    m_spi->init(spiDivisor);
+  void spiBeginTransaction(uint8_t spiDivisor) {
+    m_spi->beginTransaction(spiDivisor);
+  }
+  void spiEndTransaction() {
+    m_spi->endTransaction();
   }
   }
   uint8_t spiReceive() {
   uint8_t spiReceive() {
     return m_spi->receive();
     return m_spi->receive();
@@ -265,10 +284,8 @@ class SdSpiCard {
   void spiSend(const uint8_t* buf, size_t n) {
   void spiSend(const uint8_t* buf, size_t n) {
     m_spi->send(buf, n);
     m_spi->send(buf, n);
   }
   }
-  bool useSpiTransactions() {
-    return m_spi->useSpiTransactions();
-  }
   m_spi_t* m_spi;
   m_spi_t* m_spi;
+  bool m_selected;
   uint8_t m_chipSelectPin;
   uint8_t m_chipSelectPin;
   uint8_t m_errorCode;
   uint8_t m_errorCode;
   uint8_t m_sckDivisor;
   uint8_t m_sckDivisor;
@@ -298,9 +315,13 @@ class Sd2Card : public SdSpiCard {
   bool init(uint8_t sckDivisor = 2, uint8_t chipSelectPin = SS) {
   bool init(uint8_t sckDivisor = 2, uint8_t chipSelectPin = SS) {
     return begin(chipSelectPin, sckDivisor);
     return begin(chipSelectPin, sckDivisor);
   }
   }
+
  private:
  private:
   bool begin(m_spi_t* spi, uint8_t chipSelectPin = SS,
   bool begin(m_spi_t* spi, uint8_t chipSelectPin = SS,
              uint8_t sckDivisor = SPI_FULL_SPEED) {
              uint8_t sckDivisor = SPI_FULL_SPEED) {
+    (void)spi;
+    (void)chipSelectPin;
+    (void)sckDivisor;
     return false;
     return false;
   }
   }
   SpiDefault_t m_spi;
   SpiDefault_t m_spi;

+ 102 - 0
SdFat/src/SdSpiCard/SdSpiESP8266.cpp

@@ -0,0 +1,102 @@
+/* Arduino SdSpi Library
+ * Copyright (C) 2016 by William Greiman
+ *
+ * STM32F1 code for Maple and Maple Mini support, 2015 by Victor Perez
+ *
+ * This file is part of the Arduino SdSpi Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdSpi Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#if defined(ESP8266)
+#include "SdSpi.h"
+//------------------------------------------------------------------------------
+/** Initialize the SPI bus.
+ *
+ * \param[in] chipSelectPin SD card chip select pin.
+ */
+void SdSpi::begin(uint8_t chipSelectPin) {
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
+  SPI.begin();
+}
+//------------------------------------------------------------------------------
+/** Set SPI options for access to SD/SDHC cards.
+ *
+ * \param[in] divisor SCK clock divider relative to the max SPI clock.
+ */
+void SdSpi::beginTransaction(uint8_t divisor) {
+  const uint32_t F_SPI_MAX = 80000000;
+#if ENABLE_SPI_TRANSACTIONS
+  // Note: ESP8266 beginTransaction does not protect for interrupts.
+  SPISettings settings(F_SPI_MAX/(divisor ? divisor : 1), MSBFIRST, SPI_MODE0);
+  SPI.beginTransaction(settings);
+#else  // ENABLE_SPI_TRANSACTIONS
+  // Note: ESP8266 beginTransaction is the same as following code.
+  SPI.setFrequency(F_SPI_MAX/(divisor ? divisor : 1));
+  SPI.setBitOrder(MSBFIRST);
+  SPI.setDataMode(SPI_MODE0);
+#endif  // ENABLE_SPI_TRANSACTIONS
+}
+//------------------------------------------------------------------------------
+void SdSpi::endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+  // Note: endTransaction is an empty function on ESP8266.
+  SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
+}
+//------------------------------------------------------------------------------
+/** Receive a byte.
+ *
+ * \return The byte.
+ */
+uint8_t SdSpi::receive() {
+  return SPI.transfer(0XFF);
+}
+//------------------------------------------------------------------------------
+/** Receive multiple bytes.
+ *
+ * \param[out] buf Buffer to receive the data.
+ * \param[in] n Number of bytes to receive.
+ *
+ * \return Zero for no error or nonzero error code.
+ */
+uint8_t SdSpi::receive(uint8_t* buf, size_t n) {
+  // Works without 32-bit alignment of buf.
+  SPI.transferBytes(0, buf, n);
+  return 0;
+}
+//------------------------------------------------------------------------------
+/** Send a byte.
+ *
+ * \param[in] b Byte to send
+ */
+void SdSpi::send(uint8_t b) {
+  SPI.transfer(b);
+}
+//------------------------------------------------------------------------------
+/** Send multiple bytes.
+ *
+ * \param[in] buf Buffer for data to be sent.
+ * \param[in] n Number of bytes to send.
+ */
+void SdSpi::send(const uint8_t* buf , size_t n) {
+  // Adjust to 32-bit alignment.
+  while ((reinterpret_cast<uintptr_t>(buf) & 0X3) && n) {
+    SPI.transfer(*buf++);
+    n--;
+  }
+  SPI.transferBytes(const_cast<uint8_t*>(buf), 0, n);
+}
+#endif  // defined(ESP8266)

+ 110 - 0
SdFat/src/SdSpiCard/SdSpiParticle.cpp

@@ -0,0 +1,110 @@
+/* Arduino SdFat Library
+ * Copyright (C) 2016 by William Greiman
+ *
+ * This file is part of the Arduino SdFat Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdFat Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#include "SdSpi.h"
+#if defined(PLATFORM_ID)
+
+static  uint32_t bugDelay = 0;  // fix for SPI DMA bug.
+
+static volatile bool SPI_DMA_TransferCompleted = false;
+
+static SPIClass* const spiPtr[] = {
+  &SPI
+#if Wiring_SPI1
+  , &SPI1
+#if  Wiring_SPI2
+  , &SPI2
+#endif  // Wiring_SPI2
+#endif  // Wiring_SPI1
+};
+#if SPI_INTERFACE_COUNT == 1
+const uint8_t m_spiIf = 0;
+#endif
+//-----------------------------------------------------------------------------
+void SD_SPI_DMA_TransferComplete_Callback(void) {
+    SPI_DMA_TransferCompleted = true;
+}
+//------------------------------------------------------------------------------
+void SdSpi::begin(uint8_t chipSelectPin) {
+  spiPtr[m_spiIf]->begin(chipSelectPin);
+}
+//------------------------------------------------------------------------------
+void SdSpi::beginTransaction(uint8_t divisor) {
+  spiPtr[m_spiIf]->setBitOrder(MSBFIRST);
+  spiPtr[m_spiIf]->setDataMode(SPI_MODE0);
+#ifndef SPI_CLOCK_DIV128
+  spiPtr[m_spiIf]->setClockDivider(divisor);
+#else  // SPI_CLOCK_DIV128
+  int v;
+  if (divisor <= 2) {
+    v = SPI_CLOCK_DIV2;
+  } else  if (divisor <= 4) {
+    v = SPI_CLOCK_DIV4;
+  } else  if (divisor <= 8) {
+    v = SPI_CLOCK_DIV8;
+  } else  if (divisor <= 16) {
+    v = SPI_CLOCK_DIV16;
+  } else  if (divisor <= 32) {
+    v = SPI_CLOCK_DIV32;
+  } else  if (divisor <= 64) {
+    v = SPI_CLOCK_DIV64;
+  } else {
+    v = SPI_CLOCK_DIV128;
+  }
+  spiPtr[m_spiIf]->setClockDivider(v);
+#endif  // SPI_CLOCK_DIV128
+  // delay for SPI transfer done callback too soon bug.
+  bugDelay = 24*divisor*(1 + m_spiIf)/60;
+}
+//-----------------------------------------------------------------------------
+void SdSpi::endTransaction() {
+}
+//-----------------------------------------------------------------------------
+/** SPI receive a byte */
+uint8_t SdSpi::receive() {
+  return spiPtr[m_spiIf]->transfer(0xFF);
+}
+//-----------------------------------------------------------------------------
+uint8_t SdSpi::receive(uint8_t* buf, size_t n) {
+  SPI_DMA_TransferCompleted = false;
+  spiPtr[m_spiIf]->transfer(0, buf, n, SD_SPI_DMA_TransferComplete_Callback);
+  while (!SPI_DMA_TransferCompleted) {}
+  if (bugDelay) {
+    delayMicroseconds(bugDelay);
+  }
+  return 0;
+}
+//-----------------------------------------------------------------------------
+/** SPI send a byte */
+void SdSpi::send(uint8_t b) {
+  spiPtr[m_spiIf]->transfer(b);
+}
+//-----------------------------------------------------------------------------
+void SdSpi::send(const uint8_t* buf , size_t n) {
+  SPI_DMA_TransferCompleted = false;
+
+  spiPtr[m_spiIf]->transfer(const_cast<uint8_t*>(buf), 0, n,
+                            SD_SPI_DMA_TransferComplete_Callback);
+
+  while (!SPI_DMA_TransferCompleted) {}
+  if (bugDelay) {
+    delayMicroseconds(bugDelay);
+  }
+}
+#endif  // defined(PLATFORM_ID)

+ 13 - 2
SdFat/SdSpiSAM3X.cpp → SdFat/src/SdSpiCard/SdSpiSAM3X.cpp

@@ -57,7 +57,9 @@ static bool dmac_channel_transfer_done(uint32_t ul_num) {
   return (DMAC->DMAC_CHSR & (DMAC_CHSR_ENA0 << ul_num)) ? false : true;
   return (DMAC->DMAC_CHSR & (DMAC_CHSR_ENA0 << ul_num)) ? false : true;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
-void SdSpi::begin() {
+void SdSpi::begin(uint8_t chipSelectPin) {
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
   PIO_Configure(
   PIO_Configure(
     g_APinDescription[PIN_SPI_MOSI].pPort,
     g_APinDescription[PIN_SPI_MOSI].pPort,
     g_APinDescription[PIN_SPI_MOSI].ulPinType,
     g_APinDescription[PIN_SPI_MOSI].ulPinType,
@@ -132,7 +134,10 @@ static void spiDmaTX(const uint8_t* src, uint16_t count) {
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 //  initialize SPI controller
 //  initialize SPI controller
-void SdSpi::init(uint8_t sckDivisor) {
+void SdSpi::beginTransaction(uint8_t sckDivisor) {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.beginTransaction(SPISettings());
+#endif  // ENABLE_SPI_TRANSACTIONS
   uint8_t scbr = sckDivisor;
   uint8_t scbr = sckDivisor;
   Spi* pSpi = SPI0;
   Spi* pSpi = SPI0;
   //  disable SPI
   //  disable SPI
@@ -147,6 +152,12 @@ void SdSpi::init(uint8_t sckDivisor) {
   pSpi->SPI_CR |= SPI_CR_SPIEN;
   pSpi->SPI_CR |= SPI_CR_SPIEN;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+void SdSpi::endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
+}
+//------------------------------------------------------------------------------
 static inline uint8_t spiTransfer(uint8_t b) {
 static inline uint8_t spiTransfer(uint8_t b) {
   Spi* pSpi = SPI0;
   Spi* pSpi = SPI0;
 
 

+ 125 - 0
SdFat/src/SdSpiCard/SdSpiSTM32F1.cpp

@@ -0,0 +1,125 @@
+/* Arduino SdSpi Library
+ * Copyright (C) 2013 by William Greiman
+ *
+ * This file is part of the Arduino SdSpi Library
+ *
+ * This Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the Arduino SdSpi Library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+#if defined(__STM32F1__)
+#include "SdSpi.h"
+#define USE_STM32F1_DMAC 1
+//------------------------------------------------------------------------------
+/** Initialize the SPI bus.
+ *
+ * \param[in] chipSelectPin SD card chip select pin.
+ */
+void SdSpi::begin(uint8_t chipSelectPin) {
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
+  SPI.begin();
+}
+//------------------------------------------------------------------------------
+/** Set SPI options for access to SD/SDHC cards.
+ *
+ * \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock.
+ */
+void SdSpi::beginTransaction(uint8_t divisor) {
+#if ENABLE_SPI_TRANSACTIONS
+  // Correct divisor will be set below.
+  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
+#endif  // ENABLE_SPI_TRANSACTIONS
+  uint32_t br;  // Baud rate control field in SPI_CR1.
+  if (divisor <= 2) {
+    br = SPI_CLOCK_DIV2;
+  } else  if (divisor <= 4) {
+    br = SPI_CLOCK_DIV4;
+  } else  if (divisor <= 8) {
+    br = SPI_CLOCK_DIV8;
+  } else  if (divisor <= 16) {
+    br = SPI_CLOCK_DIV16;
+  } else  if (divisor <= 32) {
+    br = SPI_CLOCK_DIV32;
+  } else  if (divisor <= 64) {
+    br = SPI_CLOCK_DIV64;
+  } else  if (divisor <= 128) {
+    br = SPI_CLOCK_DIV128;
+  } else {
+    br = SPI_CLOCK_DIV256;
+  }
+  SPI.setClockDivider(br);
+#if !ENABLE_SPI_TRANSACTIONS
+  SPI.setBitOrder(MSBFIRST);
+  SPI.setDataMode(SPI_MODE0);
+#endif  // !ENABLE_SPI_TRANSACTIONS
+}
+//------------------------------------------------------------------------------
+/**
+ * End SPI transaction.
+ */
+void SdSpi::endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
+}
+//------------------------------------------------------------------------------
+/** Receive a byte.
+ *
+ * \return The byte.
+ */
+uint8_t SdSpi::receive() {
+  return SPI.transfer(0XFF);
+}
+//------------------------------------------------------------------------------
+/** Receive multiple bytes.
+ *
+ * \param[out] buf Buffer to receive the data.
+ * \param[in] n Number of bytes to receive.
+ *
+ * \return Zero for no error or nonzero error code.
+ */
+uint8_t SdSpi::receive(uint8_t* buf, size_t n) {
+  int rtn = 0;
+#if USE_STM32F1_DMAC
+  rtn = SPI.dmaTransfer(0, const_cast<uint8*>(buf), n);
+#else  // USE_STM32F1_DMAC
+//  SPI.read(buf, n);
+  for (size_t i = 0; i < n; i++) {
+    buf[i] = SPI.transfer(0XFF);
+  }
+#endif  // USE_STM32F1_DMAC
+  return rtn;
+}
+//------------------------------------------------------------------------------
+/** Send a byte.
+ *
+ * \param[in] b Byte to send
+ */
+void SdSpi::send(uint8_t b) {
+  SPI.transfer(b);
+}
+//------------------------------------------------------------------------------
+/** Send multiple bytes.
+ *
+ * \param[in] buf Buffer for data to be sent.
+ * \param[in] n Number of bytes to send.
+ */
+void SdSpi::send(const uint8_t* buf , size_t n) {
+#if USE_STM32F1_DMAC
+  SPI.dmaSend(const_cast<uint8*>(buf), n);
+#else  // #if USE_STM32F1_DMAC
+  SPI.write(buf, n);
+#endif  // USE_STM32F1_DMAC
+}
+#endif  // USE_NATIVE_STM32F1_SPI

+ 21 - 6
SdFat/SdSpiTeensy3.cpp → SdFat/src/SdSpiCard/SdSpiTeensy3.cpp

@@ -40,7 +40,9 @@
 /**
 /**
  * initialize SPI pins
  * initialize SPI pins
  */
  */
-void SdSpi::begin() {
+void SdSpi::begin(uint8_t chipSelectPin) {
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
   SIM_SCGC6 |= SIM_SCGC6_SPI0;
   SIM_SCGC6 |= SIM_SCGC6_SPI0;
 }
 }
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
@@ -48,9 +50,11 @@ void SdSpi::begin() {
  * Initialize hardware SPI
  * Initialize hardware SPI
  *
  *
  */
  */
-void SdSpi::init(uint8_t sckDivisor) {
+void SdSpi::beginTransaction(uint8_t sckDivisor) {
   uint32_t ctar, ctar0, ctar1;
   uint32_t ctar, ctar0, ctar1;
-
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.beginTransaction(SPISettings());
+#endif  // #if ENABLE_SPI_TRANSACTIONS
   if (sckDivisor <= 2) {
   if (sckDivisor <= 2) {
     // 1/2 speed
     // 1/2 speed
     ctar = SPI_CTAR_DBR | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
     ctar = SPI_CTAR_DBR | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
@@ -224,20 +228,25 @@ void SdSpi::send(const uint8_t* buf , size_t n) {
 #else  // KINETISK
 #else  // KINETISK
 //==============================================================================
 //==============================================================================
 // Use standard SPI library if not KINETISK
 // Use standard SPI library if not KINETISK
-#include "SPI.h"
 /**
 /**
  * Initialize SPI pins.
  * Initialize SPI pins.
  */
  */
-void SdSpi::begin() {
+void SdSpi::begin(uint8_t chipSelectPin) {
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
   SPI.begin();
   SPI.begin();
 }
 }
 /** Set SPI options for access to SD/SDHC cards.
 /** Set SPI options for access to SD/SDHC cards.
  *
  *
  * \param[in] divisor SCK clock divider relative to the system clock.
  * \param[in] divisor SCK clock divider relative to the system clock.
  */
  */
-void SdSpi::init(uint8_t divisor) {
+void SdSpi::beginTransaction(uint8_t divisor) {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.beginTransaction(SPISettings());
+#else  // #if ENABLE_SPI_TRANSACTIONS
   SPI.setBitOrder(MSBFIRST);
   SPI.setBitOrder(MSBFIRST);
   SPI.setDataMode(SPI_MODE0);
   SPI.setDataMode(SPI_MODE0);
+#endif  // #if ENABLE_SPI_TRANSACTIONS
 #ifndef SPI_CLOCK_DIV128
 #ifndef SPI_CLOCK_DIV128
   SPI.setClockDivider(divisor);
   SPI.setClockDivider(divisor);
 #else  // SPI_CLOCK_DIV128
 #else  // SPI_CLOCK_DIV128
@@ -298,4 +307,10 @@ void SdSpi::send(const uint8_t* buf , size_t n) {
   }
   }
 }
 }
 #endif  // KINETISK
 #endif  // KINETISK
+//------------------------------------------------------------------------------
+void SdSpi::endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
+}
 #endif  // defined(__arm__) && defined(CORE_TEENSY)
 #endif  // defined(__arm__) && defined(CORE_TEENSY)

+ 12 - 20
SdFat/utility/SoftSPI.h → SdFat/src/SdSpiCard/SoftSPI.h

@@ -18,7 +18,7 @@
  * <http://www.gnu.org/licenses/>.
  * <http://www.gnu.org/licenses/>.
  */
  */
 /**
 /**
- * @file
+ * @file 
  * @brief  Software SPI.
  * @brief  Software SPI.
  *
  *
  * @defgroup softSPI Software SPI
  * @defgroup softSPI Software SPI
@@ -34,13 +34,13 @@
 #define nop asm volatile ("nop\n\t")
 #define nop asm volatile ("nop\n\t")
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /** Pin Mode for MISO is input.*/
 /** Pin Mode for MISO is input.*/
-const bool MISO_MODE  = false;
+#define MISO_MODE INPUT
 /** Pullups disabled for MISO are disabled. */
 /** Pullups disabled for MISO are disabled. */
-const bool MISO_LEVEL = false;
+#define MISO_LEVEL false
 /** Pin Mode for MOSI is output.*/
 /** Pin Mode for MOSI is output.*/
-const bool MOSI_MODE  = true;
+#define MOSI_MODE  OUTPUT
 /** Pin Mode for SCK is output. */
 /** Pin Mode for SCK is output. */
-const bool SCK_MODE   = true;
+#define SCK_MODE  OUTPUT
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 /**
 /**
  * @class SoftSPI
  * @class SoftSPI
@@ -110,13 +110,9 @@ class SoftSPI {
  private:
  private:
   //----------------------------------------------------------------------------
   //----------------------------------------------------------------------------
   inline __attribute__((always_inline))
   inline __attribute__((always_inline))
-  bool MODE_CPHA(uint8_t mode) {
-    return (mode & 1) != 0;
-  }
+  bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
   inline __attribute__((always_inline))
   inline __attribute__((always_inline))
-  bool MODE_CPOL(uint8_t mode) {
-    return (mode & 2) != 0;
-  }
+  bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
   inline __attribute__((always_inline))
   inline __attribute__((always_inline))
   void receiveBit(uint8_t bit, uint8_t* data) {
   void receiveBit(uint8_t bit, uint8_t* data) {
     if (MODE_CPHA(Mode)) {
     if (MODE_CPHA(Mode)) {
@@ -125,10 +121,8 @@ class SoftSPI {
     nop;
     nop;
     nop;
     nop;
     fastDigitalWrite(SckPin,
     fastDigitalWrite(SckPin,
-                     MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
-    if (fastDigitalRead(MisoPin)) {
-      *data |= 1 << bit;
-    }
+      MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
+    if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
     if (!MODE_CPHA(Mode)) {
     if (!MODE_CPHA(Mode)) {
       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
     }
     }
@@ -141,7 +135,7 @@ class SoftSPI {
     }
     }
     fastDigitalWrite(MosiPin, data & (1 << bit));
     fastDigitalWrite(MosiPin, data & (1 << bit));
     fastDigitalWrite(SckPin,
     fastDigitalWrite(SckPin,
-                     MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
+      MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
     nop;
     nop;
     nop;
     nop;
     if (!MODE_CPHA(Mode)) {
     if (!MODE_CPHA(Mode)) {
@@ -156,10 +150,8 @@ class SoftSPI {
     }
     }
     fastDigitalWrite(MosiPin, txData & (1 << bit));
     fastDigitalWrite(MosiPin, txData & (1 << bit));
     fastDigitalWrite(SckPin,
     fastDigitalWrite(SckPin,
-                     MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
-    if (fastDigitalRead(MisoPin)) {
-      *rxData |= 1 << bit;
-    }
+      MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
+    if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
     if (!MODE_CPHA(Mode)) {
     if (!MODE_CPHA(Mode)) {
       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
     }
     }

+ 37 - 0
SdFat/src/SdSpiCard/boards/AvrDevelopersGpioPinMap.h

@@ -0,0 +1,37 @@
+#ifndef AvrDevelopersGpioPinMap_h
+#define AvrDevelopersGpioPinMap_h
+static const GpioPinMap_t GpioPinMap[] = {
+  GPIO_PIN(B, 0),  // D0
+  GPIO_PIN(B, 1),  // D1
+  GPIO_PIN(B, 2),  // D2
+  GPIO_PIN(B, 3),  // D3
+  GPIO_PIN(B, 4),  // D4
+  GPIO_PIN(B, 5),  // D5
+  GPIO_PIN(B, 6),  // D6
+  GPIO_PIN(B, 7),  // D7
+  GPIO_PIN(D, 0),  // D8
+  GPIO_PIN(D, 1),  // D9
+  GPIO_PIN(D, 2),  // D10
+  GPIO_PIN(D, 3),  // D11
+  GPIO_PIN(D, 4),  // D12
+  GPIO_PIN(D, 5),  // D13
+  GPIO_PIN(D, 6),  // D14
+  GPIO_PIN(D, 7),  // D15
+  GPIO_PIN(C, 0),  // D16
+  GPIO_PIN(C, 1),  // D17
+  GPIO_PIN(C, 2),  // D18
+  GPIO_PIN(C, 3),  // D19
+  GPIO_PIN(C, 4),  // D20
+  GPIO_PIN(C, 5),  // D21
+  GPIO_PIN(C, 6),  // D22
+  GPIO_PIN(C, 7),  // D23
+  GPIO_PIN(A, 7),  // D24
+  GPIO_PIN(A, 6),  // D25
+  GPIO_PIN(A, 5),  // D26
+  GPIO_PIN(A, 4),  // D27
+  GPIO_PIN(A, 3),  // D28
+  GPIO_PIN(A, 2),  // D29
+  GPIO_PIN(A, 1),  // D30
+  GPIO_PIN(A, 0)   // D31
+};
+#endif  // AvrDevelopersGpioPinMap_h

+ 37 - 0
SdFat/src/SdSpiCard/boards/BobuinoGpioPinMap.h

@@ -0,0 +1,37 @@
+#ifndef BobuinoGpioPinMap_h
+#define BobuinoGpioPinMap_h
+static const GpioPinMap_t GpioPinMap[] = {
+  GPIO_PIN(B, 0),  // D0
+  GPIO_PIN(B, 1),  // D1
+  GPIO_PIN(B, 2),  // D2
+  GPIO_PIN(B, 3),  // D3
+  GPIO_PIN(B, 4),  // D4
+  GPIO_PIN(B, 5),  // D5
+  GPIO_PIN(B, 6),  // D6
+  GPIO_PIN(B, 7),  // D7
+  GPIO_PIN(D, 0),  // D8
+  GPIO_PIN(D, 1),  // D9
+  GPIO_PIN(D, 2),  // D10
+  GPIO_PIN(D, 3),  // D11
+  GPIO_PIN(D, 4),  // D12
+  GPIO_PIN(D, 5),  // D13
+  GPIO_PIN(D, 6),  // D14
+  GPIO_PIN(D, 7),  // D15
+  GPIO_PIN(C, 0),  // D16
+  GPIO_PIN(C, 1),  // D17
+  GPIO_PIN(C, 2),  // D18
+  GPIO_PIN(C, 3),  // D19
+  GPIO_PIN(C, 4),  // D20
+  GPIO_PIN(C, 5),  // D21
+  GPIO_PIN(C, 6),  // D22
+  GPIO_PIN(C, 7),  // D23
+  GPIO_PIN(A, 0),  // D24
+  GPIO_PIN(A, 1),  // D25
+  GPIO_PIN(A, 2),  // D26
+  GPIO_PIN(A, 3),  // D27
+  GPIO_PIN(A, 4),  // D28
+  GPIO_PIN(A, 5),  // D29
+  GPIO_PIN(A, 6),  // D30
+  GPIO_PIN(A, 7)   // D31
+};
+#endif  // BobuinoGpioPinMap_h

部分文件因为文件数量过多而无法显示