Browse Source

Commit changes from SdFat-beta

Bill Greiman 8 years ago
parent
commit
3163b54416
100 changed files with 2759 additions and 1207 deletions
  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
 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
 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,
 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
 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.
 
-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
-<CENTER>Copyright &copy; 2012, 2013, 2014, 2015 by William Greiman
+<CENTER>Copyright &copy; 2012, 2013, 2014, 2015, 2016 by William Greiman
 </CENTER>
 
 \section Intro Introduction
@@ -85,7 +85,7 @@ developed to test %SdFat and illustrate its use.
 \section Install Installation
 
 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.
 
@@ -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.
 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
-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
 
@@ -285,11 +282,10 @@ display properly.  Examples this type name are UPPER.low, lower.TXT,
 UPPER.TXT, and lower.txt. 
 
 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.
 
-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
 directory information.  This includes writing the current data block, reading
 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.
 
-cin_cout - Demo of ArduinoInStream and ArduinoOutStream.
-
 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.
 
@@ -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.
 
-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.
 
@@ -382,11 +382,13 @@ SdInfo - Initialize an SD card and analyze its structure for trouble shooting.
 
 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.
 
 Timestamp - Sets file create, modify, and access timestamps.
 
 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
 // uses RTClib from https://github.com/adafruit/RTClib
 #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 USE_DS1307       0  // set nonzero to use DS1307 RTC
@@ -65,16 +65,23 @@ ostream& operator << (ostream& os, DateTime& dt) {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
-
+  
+  // Wait for USB Serial.
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
-  cout << endl << F("FreeRam: ") << FreeRam() << endl;
+  cout << endl << F("FreeStack: ") << FreeStack() << endl;
 
 #if WAIT_TO_START
   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
 
 #if USE_DS1307
@@ -184,5 +191,5 @@ void loop() {
   }
   logfile.close();
   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.
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 SdFat sd;
 
 SdFile file;
-char* name[] = {
+const char* name[] = {
   "low.low", "low.Mix", "low.UP",
   "Mix.low", "Mix.Mix", "Mix.UP",
   "UP.low",  "UP.Mix",  "UP.UP"
@@ -15,9 +15,15 @@ char* name[] = {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   Serial.println("type any character to start");
-  while (Serial.read() < 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   if (!sd.begin()) {
     Serial.println("begin failed");
     return;

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

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

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

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

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

@@ -15,15 +15,19 @@ const uint16_t N_PRINT = 20000;
 File file;
 
 //------------------------------------------------------------------------------
-void error(char* s) {
+void error(const char* s) {
   Serial.println(s);
-  while(1);
+  while (1) {
+    yield();
+  }
 }
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
+  
+  // Wait for USB Serial 
   while (!Serial) {
-    // wait for Leonardo
+    yield();
   }
 }
 //------------------------------------------------------------------------------
@@ -32,22 +36,22 @@ void loop() {
   uint32_t minLatency;
   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
   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
-
   if (!SD.begin(chipSelect)) {
     error("begin");
   }
-
-
+  
   Serial.println(F("Starting print test.  Please wait.\n"));
 
   // do write test

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

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

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

@@ -4,7 +4,7 @@
  *
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 SdFat sd;
 
@@ -12,8 +12,12 @@ SdFile file;
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
+  
   if (!sd.begin()) {
     Serial.println("begin failed");
     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.
 #include <SPI.h>
 // The next two lines replace #include <SD.h>.
-#include <SdFat.h>
+#include "SdFat.h"
 SdFat SD;
 
 // SD card chip select pin - Modify the value of csPin for your SD module.
@@ -12,10 +12,13 @@ File file;
 void setup() {
   Serial.begin(9600);
   // Wait for USB Serial.
-  while(!Serial) {}
+  while(!Serial) {
+    SysCall::yield();
+  }
   Serial.println(F("Type any character to start"));
-  while (!Serial.available()) {}
-
+  while (!Serial.available()) {
+    SysCall::yield(); 
+  }
   // Initialize the SD.
   if (!SD.begin(csPin)) {
     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.
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -25,12 +25,16 @@ void setup() {
   char name[] = "append.txt";
 
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
   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
   // 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
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -54,12 +54,16 @@ void calcAverage() {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
   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
   // 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;
 
 //------------------------------------------------------------------------------
-void error(char* s) {
+void error(const char* s) {
   Serial.println(s);
-  while(1);
+  while (1) {
+    yield();
+  }
 }
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    yield();
+  }
 }
 //------------------------------------------------------------------------------
 void loop() {
@@ -33,14 +39,17 @@ void loop() {
   uint32_t minLatency;
   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
   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)) {
     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
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // create a serial output stream
 ArduinoOutStream cout(Serial);
@@ -12,7 +12,11 @@ void setup() {
   int i, j, k;    // values from parsed line
 
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(2000);
 
   // 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
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // create serial output stream
 ArduinoOutStream cout(Serial);
@@ -15,11 +15,14 @@ ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 }
 //------------------------------------------------------------------------------
 void loop() {
-  int32_t n;
+  int32_t n = 0;
 
   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
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -36,11 +36,15 @@ void logEvent(const char *msg) {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
-
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   // F() stores strings in flash to save RAM
   cout << F("Type any character to start\n");
-  while (Serial.read() <= 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   delay(400);  // catch Due reset problem
 
   // 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
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD card chip select pin
 const uint8_t chipSelect = SS;
@@ -83,13 +83,17 @@ void makeTestFile() {
   wrfile.close();
 }
 //------------------------------------------------------------------------------
-void setup(void) {
+void setup() {
   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.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
   // breadboards.  use SPI_FULL_SPEED for better performance.
@@ -103,4 +107,4 @@ void setup(void) {
 
   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
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -17,8 +17,11 @@ ArduinoOutStream cout(Serial);
 void setup() {
   int c;
   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
   // breadboards.  use SPI_FULL_SPEED for better performance.
   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.
 
+BaseExtCaseTest - Long file name test.
+
 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.
 
@@ -26,3 +30,5 @@ readlog - Read file. Demo of pathnames and current working directory.
 SD_Size - Determine flash used by SD.h example.
 
 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__
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 #include "AnalogBinLogger.h"
 //------------------------------------------------------------------------------
 // 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;
 
 // 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.
 const uint16_t ISR_TIMER0 = 160;
@@ -294,8 +294,7 @@ void adcInit(metadata_t* meta) {
   adps = ADC_PRESCALER;
 #else  // ADC_PRESCALER
   // 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--) {
     if (adcCycles >= (MIN_ADC_CYCLES << adps)) {
@@ -385,7 +384,7 @@ void adcInit(metadata_t* meta) {
   meta->cpuFrequency = F_CPU;
   float sampleRate = (float)meta->cpuFrequency/meta->sampleInterval;
   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(meta->pinNumber[i], DEC);
   }
@@ -471,7 +470,6 @@ void binaryToCsv() {
   csvStream.println();
   uint32_t tPct = millis();
   while (!Serial.available() && binFile.read(&buf, 512) == 512) {
-    uint16_t i;
     if (buf.count == 0) {
       break;
     }
@@ -782,8 +780,8 @@ void setup(void) {
   // Read the first sample pin to init the ADC.
   analogRead(PIN_LIST[0]);
 
-  Serial.print(F("FreeRam: "));
-  Serial.println(FreeRam());
+  Serial.print(F("FreeStack: "));
+  Serial.println(FreeStack());
 
   // initialize file system.
   if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
@@ -793,8 +791,10 @@ void setup(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(F("type:"));
   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("r - record ADC data"));
 
-  while(!Serial.available()) {}
+  while(!Serial.available()) {
+    SysCall::yield();
+  }
   char c = tolower(Serial.read());
   if (ERROR_LED_PIN >= 0) {
     digitalWrite(ERROR_LED_PIN, LOW);
   }
-  // Read any extra Serial data.
+  // Read any Serial data.
   do {
     delay(10);
-  } while (Serial.read() >= 0);
+  } while (Serial.available() && Serial.read() >= 0);
 
   if (c == 'c') {
     binaryToCsv();

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

@@ -2,8 +2,8 @@
 // You can use test files located in
 // SdFat/examples/LongFileName/testFiles.
 #include<SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 // SD card chip select pin.
 const uint8_t SD_CS_PIN = SS;
@@ -34,8 +34,8 @@ void setup() {
   if (!sd.begin(SD_CS_PIN)) {
     sd.initErrorHalt();
   }
-  Serial.print(F("Free RAM: "));
-  Serial.println(FreeRam());
+  Serial.print(F("FreeStack: "));
+  Serial.println(FreeStack());
   Serial.println();
 
   // List files in root directory.
@@ -63,25 +63,31 @@ void setup() {
 void loop() {
   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: "));
 
-  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"));
     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"));
   }
   Serial.println();
 
-  char last;
+  char last = 0;
 
   // 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);
   }
   // 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.
  */
 #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.
-#include "UserDataType.h"  // Edit this include file to change data_t.
 
 // Acquire a data record.
 void acquireData(data_t* data) {
@@ -30,7 +37,7 @@ void acquireData(data_t* data) {
 
 // Print a data record.
 void printData(Print* pr, data_t* data) {
-  pr->print(data->time);
+  pr->print(data->time - startMicros);
   for (int i = 0; i < ADC_DIM; i++) {
     pr->write(',');
     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.
 // The led blinks for fatal errors. The led goes on solid for SD write
 // overrun errors and logging continues.
+#undef ERROR_LED_PIN
 const int8_t ERROR_LED_PIN = -1;
 //------------------------------------------------------------------------------
 // File definitions.
@@ -381,18 +389,21 @@ void logData() {
   // Wait for Serial Idle.
   Serial.flush();
   delay(10);
+  bool closeFile = false;
   uint32_t bn = 0;
   uint32_t t0 = millis();
   uint32_t t1 = t0;
   uint32_t overrun = 0;
   uint32_t overrunTotal = 0;
   uint32_t count = 0;
+  uint32_t maxDelta = 0;
+  uint32_t minDelta = 99999;
   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) {
     // Time for next data record.
     logTime += LOG_INTERVAL_USEC;
@@ -401,7 +412,7 @@ void logData() {
     }
 
     if (closeFile) {
-      if (curBlock != 0 && curBlock->count >= 0) {
+      if (curBlock != 0) {
         // Put buffer in full queue.
         fullQueue[fullHead] = curBlock;
         fullHead = queueNext(fullHead);
@@ -415,21 +426,30 @@ void logData() {
         curBlock->overrun = overrun;
         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) {
         overrun++;
       } else {
+        if (useSharedSpi) {
+          sd.card()->chipSelectHigh();
+        }
         acquireData(&curBlock->data[curBlock->count++]);
+        if (useSharedSpi) {
+          sd.card()->chipSelectLow();
+        }        
         if (curBlock->count == DATA_DIM) {
           fullQueue[fullHead] = curBlock;
           fullHead = queueNext(fullHead);
           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.print(F("Record time sec: "));
   Serial.println(0.001*(t1 - t0), 3);
+  Serial.print(minDelta);
+  Serial.print(F(" <= jitter microseconds <= "));
+  Serial.println(maxDelta);  
   Serial.print(F("Sample count: "));
   Serial.println(count);
   Serial.print(F("Samples/sec: "));
@@ -504,10 +527,14 @@ void setup(void) {
     pinMode(ERROR_LED_PIN, OUTPUT);
   }
   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.println(DATA_DIM);
   if (sizeof(block_t) != 512) {
@@ -521,8 +548,10 @@ void setup(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(F("type:"));
   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("r - record data"));
 
-  while(!Serial.available()) {}
+  while(!Serial.available()) {
+    SysCall::yield();
+  }
   char c = tolower(Serial.read());
 
   // Discard extra Serial data.
   do {
     delay(10);
-  } while (Serial.read() >= 0);
+  } while (Serial.available() && Serial.read() >= 0);
 
   if (ERROR_LED_PIN >= 0) {
     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.
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
-// SD chip select pin
+// SD default chip select pin.
 const uint8_t chipSelect = SS;
 
 // file system object
@@ -14,9 +14,16 @@ SdFile file;
 //------------------------------------------------------------------------------
 void setup() {
   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
   // breadboards.  use SPI_FULL_SPEED for better performance.
@@ -24,7 +31,10 @@ void setup() {
     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)) {
     file.printFileSize(&Serial);
     Serial.write(' ');

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

@@ -2,8 +2,8 @@
  * This program is a simple Print benchmark.
  */
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -25,8 +25,9 @@ ArduinoOutStream cout(Serial);
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
+  // Wait for USB Serial 
   while (!Serial) {
-    // wait for Leonardo
+    SysCall::yield();
   }
 }
 //------------------------------------------------------------------------------
@@ -35,15 +36,18 @@ void loop() {
   uint32_t minLatency;
   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");
-  while (Serial.read() <= 0) {
+  while (!Serial.available()) {
+    SysCall::yield();
   }
   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.
   // try SPI_HALF_SPEED if bus errors occur.

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

@@ -1,7 +1,7 @@
 // Quick hardware test.
 //
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 //
 // Set DISABLE_CHIP_SELECT to disable a second SPI device.
 // For example, with the Ethernet shield, set DISABLE_CHIP_SELECT
@@ -39,8 +39,11 @@ void reformatMsg() {
 
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // Wait for Leonardo.
-
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   cout << F("\nSPI pins:\n");
   cout << F("MISO: ") << int(MISO) << endl;
   cout << F("MOSI: ") << int(MOSI) << endl;
@@ -64,8 +67,10 @@ void setup() {
 
 bool firstTry = true;
 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) {
     cout << F("\nRestarting\n");
@@ -73,9 +78,9 @@ void loop() {
   firstTry = false;
 
   cout << F("\nEnter the chip select pin number: ");
-  while (!Serial.available()) {}
-  delay(400);  // catch Due restart problem
-
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   cin.readline();
   if (cin >> chipSelect) {
     cout << chipSelect << endl;
@@ -150,8 +155,12 @@ void loop() {
     reformatMsg();
     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");
-  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.
  *
  * 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
  * 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.
  */
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 // SD chip select pin
 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
 SdFat sd;
@@ -42,26 +42,27 @@ ArduinoOutStream cout(Serial);
 // store error strings in flash to save RAM
 #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) {
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
 }
 //------------------------------------------------------------------------------
 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");
-  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.
   // try SPI_HALF_SPEED if bus errors occur.
@@ -96,28 +97,48 @@ void loop(void) {
     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
   if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
     error("writeStart failed");
   }
   // init stats
-  uint16_t overruns = 0;
+
+  delay(1000);
+  uint32_t dotCount = 0;
+  uint32_t maxQueuePrint = 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
-  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
-    uint32_t n = b;
+    uint32_t n = b++;
     for (int8_t d = 5; d >= 0; d--) {
       pCache[d] = n || d == 5 ? n % 10 + '0' : ' ';
       n /= 10;
@@ -128,45 +149,30 @@ void loop(void) {
       error("writeData failed");
     }
     tw = micros() - tw;
-
+    totalWriteTime += tw;
     // check for max write time
     if (tw > maxWriteTime) {
       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
   if (!sd.card()->writeStop()) {
     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("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
   file.close();
   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
 #include <SPI.h>
 //#include <SD.h>
-#include <SdFat.h>
+#include "SdFat.h"
 SdFat SD;
 
 File myFile;
@@ -29,11 +29,12 @@ void setup()
 {
   // Open serial communications and wait for port to open:
   Serial.begin(9600);
+  
+  // Wait for USB Serial 
   while (!Serial) {
-    ; // wait for serial port to connect. Needed for Leonardo only
+    SysCall::yield();
   }
 
-
   Serial.print("Initializing SD card...");
   // 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

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

@@ -21,17 +21,21 @@ const int chipSelect = 4;
 
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 SdFat sd;
 SdFile myFile;
 
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   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
   // Use half speed like the native library.
   // 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
 #define DEBUG_PRINT 0
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 #if DEBUG_PRINT
-#include <SdFatUtil.h>
+#include "FreeStack.h"
 #endif  // DEBUG_PRINT
 //
 // 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 << ',' << int(card.errorData()) << dec << endl;
   }
-  while (1);
+  SysCall::halt();
 }
 //------------------------------------------------------------------------------
 #if DEBUG_PRINT
 void debugPrint() {
-  cout << F("FreeRam: ") << FreeRam() << endl;
+  cout << F("FreeStack: ") << FreeStack() << endl;
   cout << F("partStart: ") << relSector << endl;
   cout << F("partSize: ") << partSize << endl;
   cout << F("reserved: ") << reservedSectors << endl;
@@ -440,8 +440,18 @@ void formatCard() {
 void setup() {
   char c;
   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(
          "\n"
          "This program can erase and/or format SD/SDHC cards.\n"
@@ -455,8 +465,9 @@ void setup() {
          "\n"
          "Warning, all data on the card will be erased.\n"
          "Enter 'Y' to continue: ");
-  while (!Serial.available()) {}
-  delay(400);  // catch Due restart problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
   c = Serial.read();
   cout << c << endl;
@@ -464,8 +475,10 @@ void setup() {
     cout << F("Quiting, you did not enter 'Y'.\n");
     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(
          "\n"
@@ -476,7 +489,9 @@ void setup() {
          "\n"
          "Enter option: ");
 
-  while (!Serial.available()) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   c = Serial.read();
   cout << c << endl;
   if (!strchr("EFQ", c)) {
@@ -497,8 +512,8 @@ void setup() {
   }
   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') {
     eraseCard();

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

@@ -2,7 +2,7 @@
  * This program attempts to initialize an SD card and analyze its structure.
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 /*
  * SD chip select pin.  Common values are:
  *
@@ -139,18 +139,22 @@ void volDmp() {
   cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl;
   if (sd.vol()->dataStartBlock() % eraseSize) {
     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() {
   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
   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;
   if (DISABLE_CHIP_SELECT < 0) {
     cout << F(
@@ -167,13 +171,16 @@ void setup() {
 }
 //------------------------------------------------------------------------------
 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");
-  while (Serial.read() <= 0) {}
-  delay(400);  // catch Due reset problem
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
   uint32_t t = millis();
   // 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.
 //
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 #if SD_SPI_CONFIGURATION >= 3  // Must be set in SdFat/SdFatConfig.h
 //
 // Pin numbers in templates must be constants.
@@ -23,10 +23,14 @@ SdFile file;
 
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {}  // Wait for Leonardo
-
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   Serial.println("Type any character to start");
-  while (Serial.read() <= 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
 
   if (!sd.begin(SD_CHIP_SELECT_PIN)) {
     sd.initErrorHalt();
@@ -37,6 +41,12 @@ void setup() {
   }
   file.println(F("This line was printed using software SPI."));
 
+  file.rewind();
+  
+  while (file.available()) {
+    Serial.write(file.read());
+  }
+
   file.close();
 
   Serial.println(F("Done."));

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

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

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

@@ -2,8 +2,8 @@
  * Example use of three SD cards.
  */
 #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
 
 // SD1 is a microSD on hardware SPI pins 50-52
@@ -45,19 +45,22 @@ void list() {
 //------------------------------------------------------------------------------
 void setup() {
   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
-  for (int i = 0; i < sizeof(buf); i++) {
+  for (size_t i = 0; i < sizeof(buf); i++) {
     buf[i] = i;
   }
-
   Serial.println(F("type any character to start"));
-  while (Serial.read() <= 0) {}
-
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   // disable sd2 while initializing sd1
   pinMode(SD2_CS, OUTPUT);
   digitalWrite(SD2_CS, HIGH);
@@ -140,7 +143,7 @@ void setup() {
   Serial.println(F("Writing SD1:/Dir1/TEST1.bin"));
 
   // 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)) {
       sd1.errorExit("sd1.write");
     }
@@ -168,7 +171,7 @@ void setup() {
     if (n == 0) {
       break;
     }
-    if (file2.write(buf, n) != n) {
+    if ((int)file2.write(buf, n) != n) {
       sd2.errorExit("write3");
     }
   }
@@ -196,7 +199,7 @@ void setup() {
     if (n != sizeof(buf)) {
       sd2.errorExit("read2");
     }
-    if (file3.write(buf, n) != n) {
+    if ((int)file3.write(buf, n) != n) {
       sd3.errorExit("write2");
     }
   }
@@ -206,11 +209,11 @@ void setup() {
   // Verify content of file3
   file3.rewind();
   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)) {
       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]) {
         sd3.errorExit("Verify error");
       }

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

@@ -3,7 +3,7 @@
  * and the timestamp() function.
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 SdFat sd;
 
@@ -75,12 +75,14 @@ void printTimestamps(SdFile& f) {
 //------------------------------------------------------------------------------
 void setup(void) {
   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());
-  delay(400);  // catch Due reset problem
-
+  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)) {
@@ -170,4 +172,4 @@ void setup(void) {
   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.
  */
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 SdFat 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() {
   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
-  for (int i = 0; i < sizeof(buf); i++) {
+  for (size_t i = 0; i < sizeof(buf); i++) {
     buf[i] = i;
   }
 
   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
   pinMode(SD2_CS, OUTPUT);
@@ -102,7 +106,7 @@ void setup() {
   Serial.println(F("Writing test.bin to 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)) {
       sd1.errorExit("sd1.write");
     }
@@ -129,7 +133,7 @@ void setup() {
     if (n == 0) {
       break;
     }
-    if (file2.write(buf, n) != n) {
+    if ((int)file2.write(buf, n) != n) {
       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.
  */
 #include <SPI.h>
-#include <SdFat.h>
-#include <SdFatUtil.h>
+#include "SdFat.h"
+#include "FreeStack.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -15,10 +15,10 @@ const size_t BUF_SIZE = 512;
 const uint32_t FILE_SIZE_MB = 5;
 
 // Write pass count.
-const uint8_t WRITE_COUNT = 10;
+const uint8_t WRITE_COUNT = 2;
 
 // Read pass count.
-const uint8_t READ_COUNT = 5;
+const uint8_t READ_COUNT = 2;
 //==============================================================================
 // End of configuration constants.
 //------------------------------------------------------------------------------
@@ -29,6 +29,10 @@ uint8_t buf[BUF_SIZE];
 
 // file system
 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
 SdFile file;
@@ -36,7 +40,7 @@ SdFile file;
 // Serial output stream
 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))
 //------------------------------------------------------------------------------
 void cidDmp() {
@@ -62,7 +66,11 @@ void cidDmp() {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(1000);
   cout << F("\nUse a freshly formatted SD for best performance.\n");
 
@@ -77,15 +85,18 @@ void loop() {
   uint32_t minLatency;
   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
   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.
   // try SPI_HALF_SPEED if bus errors occur.
@@ -129,7 +140,9 @@ void loop() {
     for (uint32_t i = 0; i < n; i++) {
       uint32_t m = micros();
       if (file.write(buf, sizeof(buf)) != sizeof(buf)) {
-        error("write failed");
+        sd.errorPrint("write failed");
+        file.close();
+        return;
       }
       m = micros() - m;
       if (maxLatency < m) {
@@ -146,11 +159,11 @@ void loop() {
     cout << s/t <<',' << maxLatency << ',' << minLatency;
     cout << ',' << totalLatency/n << endl;
   }
-
   cout << endl << F("Starting read test, please wait.") << endl;
   cout << endl <<F("read speed and latency") << endl;
   cout << F("speed,max,min,avg") << endl;
   cout << F("KB/Sec,usec,usec,usec") << endl;
+
   // do read test
   for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) {
     file.rewind();
@@ -161,8 +174,11 @@ void loop() {
     for (uint32_t i = 0; i < n; i++) {
       buf[BUF_SIZE-1] = 0;
       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;
       if (maxLatency < m) {
@@ -176,6 +192,7 @@ void loop() {
         error("data check");
       }
     }
+    s = file.fileSize();
     t = millis() - t;
     cout << s/t <<',' << maxLatency << ',' << minLatency;
     cout << ',' << totalLatency/n << endl;

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

@@ -2,7 +2,7 @@
  * Simple data logger.
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin.  Be sure to disable any other SPI devices such as Enet.
 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
 // 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.
-const uint32_t SAMPLE_INTERVAL_MS = 200;
+const uint32_t SAMPLE_INTERVAL_MS = 1000;
 
 // Log file base name.  Must be six characters or less.
 #define FILE_BASE_NAME "Data"
@@ -67,12 +67,18 @@ void setup() {
   char fileName[13] = FILE_BASE_NAME "00.csv";
 
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(1000);
 
   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
   // breadboards.  use SPI_FULL_SPEED for better performance.
   if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
@@ -96,9 +102,10 @@ void setup() {
   if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) {
     error("file.open");
   }
+  // Read any Serial data.
   do {
     delay(10);
-  } while (Serial.read() >= 0);
+  } while (Serial.available() && Serial.read() >= 0);
 
   Serial.print(F("Logging to: "));
   Serial.println(fileName);
@@ -138,6 +145,6 @@ void loop() {
     // Close file and stop.
     file.close();
     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().
  */
-#include <SPI.h>
-#include <SdFat.h>
+#include <SPI.h> 
+#include "SdFat.h"
+
 // SD card chip select pin.
 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.
 SdFat sd;
@@ -29,40 +28,44 @@ ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  while (!Serial) {} // wait for Leonardo
+  
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(1000);
 
   cout << F("Type any character to start\n");
   // Wait for input line and discard.
   cin.readline();
-
+  cout << endl;
+  
   // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
   // breadboards.  use SPI_FULL_SPEED for better performance.
   if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) {
     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.
   if (!sd.mkdir("Folder1")) {
     error("Create Folder1 failed");
@@ -89,7 +92,7 @@ void setup() {
   file.close();
   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);
 
   // Remove files from current directory.
@@ -103,7 +106,7 @@ void setup() {
     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);
 
   // Remove Folder1.
@@ -111,7 +114,9 @@ void setup() {
     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");
 }
 //------------------------------------------------------------------------------

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

@@ -1,6 +1,6 @@
 // Demo of fgets function to read lines from a file.
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -60,10 +60,16 @@ void makeTestFile() {
 //------------------------------------------------------------------------------
 void setup(void) {
   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.read() <= 0) {}
+  while (!Serial.available()) {
+    SysCall::yield();
+  }
   delay(400);  // catch Due reset problem
 
   // 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
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // create Serial stream
 ArduinoOutStream cout(Serial);
@@ -42,7 +42,10 @@ void showDate(int m, int d, int y) {
 void setup(void) {
   Serial.begin(9600);
 
-  while (!Serial) {}  // wait for Leonardo
+  // Wait for USB Serial 
+  while (!Serial) {
+    SysCall::yield();
+  }
   delay(2000);
 
   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.
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -54,12 +54,17 @@ void testGetline() {
 //------------------------------------------------------------------------------
 void setup(void) {
   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");
-  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
   // 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;
     }
-
-    // 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() {
   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().
  */
 #include <SPI.h>
-#include <SdFat.h>
+#include "SdFat.h"
 
 // SD chip select pin
 const uint8_t chipSelect = SS;
@@ -19,11 +19,15 @@ ArduinoOutStream cout(Serial);
 //------------------------------------------------------------------------------
 void setup() {
   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;
-  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
   // 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"
 #if ENABLE_ARDUINO_FEATURES
-#include <Arduino.h>
+#include "SysCall.h"
 #include "bufstream.h"
 //==============================================================================
 /**
@@ -50,7 +50,9 @@ class ArduinoInStream : public ibufstream {
     size_t i = 0;
     uint32_t t;
     m_line[0] = '\0';
-    while (!m_hw->available()) {}
+    while (!m_hw->available()) {
+      SysCall::yield();
+    }
 
     while (1) {
       t = millis();
@@ -77,6 +79,8 @@ done:
    * \return true/false.
    */
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
   }
   /** Internal - do not use.
@@ -84,6 +88,7 @@ done:
    * \return true/false.
    */
   bool seekpos(pos_type pos) {
+    (void)pos;
     return false;
   }
 
@@ -121,9 +126,12 @@ class ArduinoOutStream : public ostream {
     m_pr->write(str);
   }
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
   }
   bool seekpos(pos_type pos) {
+    (void)pos;
     return false;
   }
   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;
     }
-//   if (read(&b, 1) != 1) {
-//     DBG_FAIL_MACRO;
-//     goto fail;
-//    }
     m_curPosition += 31;
   } else {
     m_curPosition += 32;
@@ -1107,6 +1103,10 @@ bool FatFile::seekSet(uint32_t pos) {
     DBG_FAIL_MACRO;
     goto fail;
   }
+  // Optimize O_APPEND writes.
+  if (pos == m_curPosition) {
+    return true;
+  }
   if (pos == 0) {
     // set position to start of file
     m_curCluster = 0;

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

@@ -37,10 +37,6 @@ class FatFileSystem;
 #ifdef __AVR__
 #include <avr/pgmspace.h>
 #else  // __AVR__
-#ifndef PGM_P
-/** pointer to flash for ARM */
-#define PGM_P const char*
-#endif  // PGM_P
 #ifndef PSTR
 /** store literal string in flash for ARM */
 #define PSTR(x) (x)
@@ -55,7 +51,7 @@ class FatFileSystem;
 #endif  // pgm_read_word
 #ifndef PROGMEM
 /** store in flash for ARM */
-#define PROGMEM const
+#define PROGMEM
 #endif  // PROGMEM
 #endif  // __AVR__
 //------------------------------------------------------------------------------
@@ -219,9 +215,6 @@ class FatFile {
    */
   bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
   /** 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] 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);
     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
   /** Change a volume's working directory to root
    *
@@ -180,7 +189,7 @@ fail:
    *
    * 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);
   }
   //----------------------------------------------------------------------------

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

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

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

@@ -24,6 +24,7 @@
  * \brief FatVolume class
  */
 #include <stddef.h>
+#include "SysCall.h"
 #include "FatLibConfig.h"
 #include "FatStructs.h"
 //------------------------------------------------------------------------------
@@ -31,11 +32,10 @@
 /** Macro for debug. */
 #define DEBUG_MODE 0
 #if DEBUG_MODE
-#include <Arduino.h>
 #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_HALT_IF(b) if (b) {Serial.println(F(#b));\
-                               DBG_FAIL_MACRO; while (1);}
+                               DBG_FAIL_MACRO; SysCall::halt();}
 #else  // DEBUG_MODE
 #define DBG_FAIL_MACRO
 #define DBG_PRINT_IF(b)
@@ -44,12 +44,9 @@
 #endif  // DOXYGEN_SHOULD_SKIP_THIS
 //------------------------------------------------------------------------------
 #if ENABLE_ARDUINO_FEATURES
-#include <Arduino.h>
-/** Use Print on Arduino */
+/** Use Print for Arduino */
 typedef Print print_t;
 #else  // ENABLE_ARDUINO_FEATURES
-//  Arduino type for flash string.
-class __FlashStringHelper;
 /**
  * \class CharWriter
  * \brief Character output - often serial port.
@@ -272,6 +269,25 @@ class FatVolume {
   uint32_t m_lastCluster;          // Last cluster number in FAT.
   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
   FatCache m_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;
 }
 //------------------------------------------------------------------------------
-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) {
   uint8_t* dst = reinterpret_cast<uint8_t*>(ptr);
   size_t total = size*count;
@@ -281,8 +271,9 @@ int StdioStream::write(const void* buf, size_t count) {
   return count;
 }
 //------------------------------------------------------------------------------
+#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
 size_t StdioStream::print(const __FlashStringHelper *str) {
-  const char *p = (const char PROGMEM *)str;
+  const char *p = (const char*)str;
   uint8_t c;
   while ((c = pgm_read_byte(p))) {
     if (putc(c) < 0) {
@@ -290,89 +281,14 @@ size_t StdioStream::print(const __FlashStringHelper *str) {
     }
     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) {
-#define FLOAT_NEW_WAY
-#ifdef FLOAT_NEW_WAY
   char buf[24];
   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);
-#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) {
@@ -532,7 +448,7 @@ int StdioStream::fillGet() {
 // private
 bool StdioStream::fillBuf() {
   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)) {
       m_flags |= F_ERR;
       return false;
@@ -560,7 +476,7 @@ bool StdioStream::fillBuf() {
 // private
 bool StdioStream::flushBuf() {
   if (!(m_flags &
-        F_SWR)) {  /////////////////check for F_ERR ??////////////////////////
+        F_SWR)) {  // check for F_ERR ??////////////////////////
     if (!(m_flags & F_SRW)) {
       m_flags |= F_ERR;
       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);
   //----------------------------------------------------------------------------
-  /** 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.
    *
    * 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;
   }
   //----------------------------------------------------------------------------
+#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
   /** Print a string stored in flash memory.
    *
    * \param[in] str the string to print.
@@ -421,6 +412,7 @@ class StdioStream : private FatFile {
    * \return the number of bytes written.
    */
   size_t print(const __FlashStringHelper *str);
+#endif  // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
   //----------------------------------------------------------------------------
   /** 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;
   }
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
   }
   bool seekpos(pos_type pos) {
@@ -137,6 +139,8 @@ class obufstream : public ostream {
     }
   }
   bool seekoff(off_type off, seekdir way) {
+    (void)off;
+    (void)way;
     return false;
   }
   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);
     return;
   }
+#ifdef __AVR__
   PGM_P truePtr = PSTR("true");
   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 false_len = 5;
   bool trueOk = true;
@@ -80,8 +85,13 @@ void istream::getBool(bool *b) {
   uint8_t i = 0;
   int c = readSkip();
   while (1) {
+#ifdef __AVR__
     falseOk = falseOk && c == pgm_read_byte(falsePtr + 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) {
       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
  */
 #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
@@ -194,14 +176,7 @@ class ostream : public virtual ios {
     putNum(reinterpret_cast<uint32_t>(arg));
     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.
    * \param[in] arg pointing to flash string
    * \return the stream
@@ -210,6 +185,7 @@ class ostream : public virtual ios {
     putPgm(reinterpret_cast<const char*>(arg));
     return *this;
   }
+#endif  // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
   /**
    * 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
  * <http://www.gnu.org/licenses/>.
  */
-#include <Arduino.h>
+#include "SystemInclude.h"
 #if defined(UDR0) || defined(DOXYGEN)
 #include "MinimumSerial.h"
 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
 #define MinimumSerial_h
-#include <Arduino.h>
+#include "SystemInclude.h"
 //==============================================================================
 /**
  * \class MinimumSerial

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

@@ -21,17 +21,12 @@
 //------------------------------------------------------------------------------
 void SdFatBase::errorHalt(Print* pr) {
   errorPrint(pr);
-  while (1) {}
+  SysCall::halt();
 }
 //------------------------------------------------------------------------------
 void SdFatBase::errorHalt(Print* pr, char const* 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) {
@@ -50,15 +45,9 @@ void SdFatBase::errorPrint(Print* pr, char const* msg) {
   errorPrint(pr);
 }
 //------------------------------------------------------------------------------
-void SdFatBase::errorPrint(Print* pr, const __FlashStringHelper* msg) {
-  pr->print(F("error: "));
-  pr->println(msg);
-  errorPrint(pr);
-}
-//------------------------------------------------------------------------------
 void SdFatBase::initErrorHalt(Print* pr) {
   initErrorPrint(pr);
-  while (1) {}
+  SysCall::halt();
 }
 //------------------------------------------------------------------------------
 void SdFatBase::initErrorHalt(Print* pr, char const *msg) {
@@ -66,11 +55,6 @@ void SdFatBase::initErrorHalt(Print* pr, char const *msg) {
   initErrorHalt(pr);
 }
 //------------------------------------------------------------------------------
-void SdFatBase::initErrorHalt(Print* pr, const __FlashStringHelper* msg) {
-  pr->println(msg);
-  initErrorHalt(pr);
-}
-//------------------------------------------------------------------------------
 void SdFatBase::initErrorPrint(Print* pr) {
   if (cardErrorCode()) {
     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);
   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) {
   pr->println(msg);
   initErrorPrint(pr);
 }
-
+#endif  // defined(ARDUINO) || defined(DOXYGEN)

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

@@ -23,11 +23,16 @@
  * \file
  * \brief SdFat class
  */
+#ifdef ARDUINO
+#include "SdSpiCard/SdSpiCard.h"
+#include "FatLib/FatLib.h"
+#else  // ARDUINO
 #include "SdSpiCard.h"
-#include "utility/FatLib.h"
+#include "FatLib.h"
+#endif  // ARDUINO
 //------------------------------------------------------------------------------
 /** SdFat version YYYYMMDD */
-#define SD_FAT_VERSION 20150324
+#define SD_FAT_VERSION 20160719
 //==============================================================================
 /**
  * \class SdBaseFile
@@ -51,7 +56,6 @@ class SdBaseFile : public FatFile {
  * \class SdFile
  * \brief Class for backward compatibility.
  */
-
 class SdFile : public PrintFile {
  public:
   SdFile() {}
@@ -108,19 +112,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    */
   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 */
   void errorPrint() {
     errorPrint(&Serial);
@@ -142,19 +134,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    */
   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 purposes only.
    *  \return true for success else false.
@@ -183,18 +163,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    */
   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. */
   void initErrorPrint() {
     initErrorPrint(&Serial);
@@ -217,6 +186,45 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    */
   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.
    *
    * \param[in] msg Message to print.
@@ -230,6 +238,7 @@ class SdFatBase : public FatFileSystem {
    * \param[in] msg Message to print.
    */
   void initErrorPrint(Print* pr, const __FlashStringHelper* msg);
+#endif  // defined(ARDUINO) || defined(DOXYGEN)
 
  private:
   uint8_t cardErrorCode() {
@@ -259,6 +268,15 @@ class SdFatBase : public FatFileSystem {
  */
 class SdFat : public SdFatBase {
  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.
    *
    * \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) {
     return card()->begin(&m_spi, csPin, divisor);
   }
+
  private:
   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.
  *
  * 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
  * 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 */
 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.
  *
- * 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
 //------------------------------------------------------------------------------
 /**
- * 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
- * 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.
@@ -185,4 +195,46 @@ const uint8_t SPI_SCK_INIT_DIVISOR = 128;
 #else  // RAMEND
 #define USE_MULTI_BLOCK_IO 1
 #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

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

@@ -1,5 +1,5 @@
 /* Arduino SdFat Library
- * Copyright (C) 2012 by William Greiman
+ * Copyright (C) 2015 by William Greiman
  *
  * This file is part of the Arduino SdFat Library
  *
@@ -38,14 +38,4 @@ int SdFatUtil::FreeRam() {
   return __brkval ? &top - __brkval : &top - &__bss_end;
 }
 #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 */
 uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14;  // REMOVE - not used
 /** 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 */
 uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16;
 /** 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;
 /** SPI DMA error */
 uint8_t const SD_CARD_ERROR_SPI_DMA = 0X1C;
+/** CMD6 not accepted */
+uint8_t const SD_CARD_ERROR_CMD6 = 0X1D;
 //------------------------------------------------------------------------------
 // card types
 /** Standard capacity V1 SD card */
@@ -115,17 +117,19 @@ uint8_t const SPI_SIXTEENTH_SPEED = 32;
 //------------------------------------------------------------------------------
 // SD operation timeouts
 /** init timeout ms */
-uint16_t const SD_INIT_TIMEOUT = 2000;
+unsigned const SD_INIT_TIMEOUT = 2000;
 /** erase timeout ms */
-uint16_t const SD_ERASE_TIMEOUT = 10000;
+unsigned const SD_ERASE_TIMEOUT = 10000;
 /** read timeout ms */
-uint16_t const SD_READ_TIMEOUT = 300;
+unsigned const SD_READ_TIMEOUT = 300;
 /** write time out ms */
-uint16_t const SD_WRITE_TIMEOUT = 600;
+unsigned const SD_WRITE_TIMEOUT = 600;
 //------------------------------------------------------------------------------
 // SD card commands
 /** GO_IDLE_STATE - init card in spi mode if CS low */
 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.*/
 uint8_t const CMD8 = 0X08;
 /** 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
 #define SdSpi_h
-#include <Arduino.h>
+#include "SystemInclude.h"
 #include "SdFatConfig.h"
-
 //------------------------------------------------------------------------------
 /**
  * \class SdSpiBase
@@ -33,13 +32,20 @@
  */
 class SdSpiBase {
  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.
    *
    * \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.
    *
    * \return The byte.
@@ -64,8 +70,6 @@ class SdSpiBase {
   * \param[in] n Number of bytes to send.
   */
   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 {
 #endif  // SD_SPI_CONFIGURATION >= 3
  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.
    *
    * \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.
    *
    * \return The byte.
@@ -110,9 +121,13 @@ class SdSpi {
    */
   void send(const uint8_t* buf, size_t n);
   /** \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
  *        memory cards.
  */
-#if SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1 || defined(DOXYGEN)
-#include <SPI.h>
 #if SD_SPI_CONFIGURATION >= 3
 class SdSpiLib : public SdSpiBase {
 #else  // SD_SPI_CONFIGURATION >= 3
 class SdSpiLib {
 #endif  // SD_SPI_CONFIGURATION >= 3
  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();
   }
   /** Set SPI options for access to SD/SDHC cards.
    *
    * \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.setDataMode(SPI_MODE0);
+#endif  // ENABLE_SPI_TRANSACTIONS
 #ifndef SPI_CLOCK_DIV128
     SPI.setClockDivider(divisor);
 #else  // SPI_CLOCK_DIV128
@@ -162,6 +182,14 @@ class SdSpiLib {
     }
     SPI.setClockDivider(v);
 #endif  // SPI_CLOCK_DIV128
+  }
+  /**
+   * End SPI transaction.
+   */
+  void endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+    SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
   }
   /** Receive a byte.
    *
@@ -200,15 +228,14 @@ class SdSpiLib {
       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)
-#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
  * \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>
 class SdSpiSoft : public SdSpiBase {
  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();
   }
   /**
    * Initialize hardware SPI - dummy for soft SPI
    * \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.
    *
    * \return The byte.
@@ -264,34 +300,28 @@ class SdSpiSoft : public SdSpiBase {
       send(buf[i]);
     }
   }
-  /** \return false - no SPI transactions */
-  bool useSpiTransactions() {
-    return false;
-  }
 
  private:
   SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
 };
 #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. */
 typedef SdSpiSoft<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN>
 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.
 #ifdef __AVR__
 //------------------------------------------------------------------------------
-inline void SdSpi::begin() {
+inline void SdSpi::begin(uint8_t chipSelectPin) {
 #ifdef __AVR_ATmega328P__
   // Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi.
   PORTB |= 1 << 2;  // SS high
@@ -308,9 +338,14 @@ inline void SdSpi::begin() {
   pinMode(MOSI, OUTPUT);
   pinMode(SCK, OUTPUT);
 #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 r = 0;
 
@@ -320,6 +355,12 @@ inline void SdSpi::init(uint8_t divisor) {
   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() {
   SPDR = 0XFF;
   while (!(SPSR & (1 << SPIF))) {}

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

@@ -19,12 +19,11 @@
  */
 #include "SdSpiCard.h"
 #include "SdSpi.h"
-#if ENABLE_SPI_TRANSACTION
-#include <SPI.h>
-#endif  // ENABLE_SPI_TRANSACTION
 // debug trace macro
 #define SD_TRACE(m, 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
 // CRC functions
@@ -121,25 +120,26 @@ bool SdSpiCard::begin(m_spi_t* spi, uint8_t chipSelectPin, uint8_t sckDivisor) {
   m_spi = spi;
   m_chipSelectPin = chipSelectPin;
   // 16-bit init start time allows over a minute
-  uint16_t t0 = (uint16_t)millis();
+  unsigned t0 = (unsigned)millis();
   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;
-  spiInit(m_sckDivisor);
+
+  // toggle chip select and set slow SPI clock.
+  chipSelectLow();
+  chipSelectHigh();
 
   // must supply min of 74 clock cycles with CS high.
   for (uint8_t i = 0; i < 10; i++) {
     spiSend(0XFF);
   }
-
   // command to go idle in SPI mode
   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);
       goto fail;
     }
@@ -163,7 +163,7 @@ bool SdSpiCard::begin(m_spi_t* spi, uint8_t chipSelectPin, uint8_t sckDivisor) {
       type(SD_CARD_TYPE_SD2);
       break;
     }
-    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
+    if (((unsigned)millis() - t0) > SD_INIT_TIMEOUT) {
       error(SD_CARD_ERROR_CMD8);
       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) {
     // check for timeout
-    if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
+    if (((unsigned)millis() - t0) > SD_INIT_TIMEOUT) {
       error(SD_CARD_ERROR_ACMD41);
       goto fail;
     }
@@ -204,29 +204,32 @@ fail:
 // send command and return error code.  Return zero for OK
 uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
   // select card
-  chipSelectLow();
-
+  if (!m_selected) {
+    chipSelectLow();
+  }
   // wait if busy
   waitNotBusy(SD_WRITE_TIMEOUT);
 
-  uint8_t *pa = reinterpret_cast<uint8_t *>(&arg);
-
 #if USE_SD_CRC
   // 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
-  for (uint8_t k = 0; k < 6; k++) {
-    spiSend(d[k]);
-  }
+  spiSend(buf, 6);
 #else  // USE_SD_CRC
   // send command
   spiSend(cmd | 0x40);
 
   // send argument
+  uint8_t *pa = reinterpret_cast<uint8_t *>(&arg);
   for (int8_t i = 3; i >= 0; 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() {
+  if (!m_selected) {
+    SD_CS_DBG("chipSelectHigh error");
+    return;
+  }
   digitalWrite(m_chipSelectPin, HIGH);
   // insure MISO goes high impedance
   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() {
-#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);
+  m_selected = true;
 }
 //------------------------------------------------------------------------------
 bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) {
@@ -339,15 +343,20 @@ bool SdSpiCard::eraseSingleBlockEnable() {
 }
 //------------------------------------------------------------------------------
 bool SdSpiCard::isBusy() {
-  bool rtn;
-  chipSelectLow();
+  bool rtn = true;
+  bool selected = m_selected;
+  if (!selected) {    
+    chipSelectLow();
+  }
   for (uint8_t i = 0; i < 8; i++) {
-    rtn = spiReceive() != 0XFF;
-    if (!rtn) {
+    if (0XFF == spiReceive()) {
+      rtn = false;
       break;
     }
   }
-  chipSelectHigh();
+  if (!selected) {
+    chipSelectHigh();
+  }
   return rtn;
 }
 //------------------------------------------------------------------------------
@@ -361,7 +370,11 @@ bool SdSpiCard::readBlock(uint32_t blockNumber, uint8_t* dst) {
     error(SD_CARD_ERROR_CMD17);
     goto fail;
   }
-  return readData(dst, 512);
+  if (!readData(dst, 512)) {
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
 
 fail:
   chipSelectHigh();
@@ -373,7 +386,7 @@ bool SdSpiCard::readBlocks(uint32_t block, uint8_t* dst, size_t count) {
     return false;
   }
   for (uint16_t b = 0; b < count; b++, dst += 512) {
-    if (!readData(dst)) {
+    if (!readData(dst, 512)) {
       return false;
     }
   }
@@ -381,8 +394,10 @@ bool SdSpiCard::readBlocks(uint32_t block, uint8_t* dst, size_t count) {
 }
 //------------------------------------------------------------------------------
 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) {
@@ -390,9 +405,9 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
   uint16_t crc;
 #endif  // USE_SD_CRC
   // wait for start block token
-  uint16_t t0 = millis();
+  unsigned t0 = millis();
   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);
       goto fail;
     }
@@ -419,7 +434,6 @@ bool SdSpiCard::readData(uint8_t* dst, size_t count) {
   spiReceive();
   spiReceive();
 #endif  // USE_SD_CRC
-  chipSelectHigh();
   return true;
 
 fail:
@@ -452,7 +466,11 @@ bool SdSpiCard::readRegister(uint8_t cmd, void* buf) {
     error(SD_CARD_ERROR_READ_REG);
     goto fail;
   }
-  return readData(dst, 16);
+  if (!readData(dst, 16)) {
+    goto fail;
+  }
+  chipSelectHigh();
+  return true;
 
 fail:
   chipSelectHigh();
@@ -468,7 +486,6 @@ bool SdSpiCard::readStart(uint32_t blockNumber) {
     error(SD_CARD_ERROR_CMD18);
     goto fail;
   }
-  chipSelectHigh();
   return true;
 
 fail:
@@ -491,12 +508,11 @@ fail:
 //------------------------------------------------------------------------------
 // wait for card to go not busy
 bool SdSpiCard::waitNotBusy(uint16_t timeoutMillis) {
-  uint16_t t0 = millis();
+  unsigned t0 = millis();
   while (spiReceive() != 0XFF) {
-    if (((uint16_t)millis() - t0) >= timeoutMillis) {
+    if (((unsigned)millis() - t0) >= timeoutMillis) {
       goto fail;
     }
-    spiYield();
   }
   return true;
 
@@ -542,30 +558,32 @@ fail:
 //------------------------------------------------------------------------------
 bool SdSpiCard::writeBlocks(uint32_t block, const uint8_t* src, size_t count) {
   if (!writeStart(block, count)) {
-    return false;
+    goto fail;
   }
   for (size_t b = 0; b < count; b++, src += 512) {
     if (!writeData(src)) {
-      return false;
+      goto fail;
     }
   }
   return writeStop();
+
+ fail:
+  chipSelectHigh();
+  return false;
 }
 //------------------------------------------------------------------------------
 bool SdSpiCard::writeData(const uint8_t* src) {
-  chipSelectLow();
   // wait for previous write to finish
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
+    error(SD_CARD_ERROR_WRITE_TIMEOUT);
     goto fail;
   }
   if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
     goto fail;
   }
-  chipSelectHigh();
   return true;
 
 fail:
-  error(SD_CARD_ERROR_WRITE_MULTIPLE);
   chipSelectHigh();
   return false;
 }
@@ -609,7 +627,6 @@ bool SdSpiCard::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
     error(SD_CARD_ERROR_CMD25);
     goto fail;
   }
-  chipSelectHigh();
   return true;
 
 fail:
@@ -618,7 +635,6 @@ fail:
 }
 //------------------------------------------------------------------------------
 bool SdSpiCard::writeStop() {
-  chipSelectLow();
   if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
     goto fail;
   }

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

@@ -23,10 +23,10 @@
  * \file
  * \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
@@ -41,7 +41,8 @@ class SdSpiCard {
   typedef SdSpiBase m_spi_t;
 #endif  // SD_SPI_CONFIGURATION < 3
   /** 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.
    * \param[in] spi SPI object.
    * \param[in] chipSelectPin SD chip select pin.
@@ -57,6 +58,16 @@ class SdSpiCard {
    *         or zero if an error occurs.
    */
   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.
    *
    * \param[in] firstBlock The address of the first block in the range.
@@ -180,6 +191,14 @@ class SdSpiCard {
   uint8_t 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 0 - SD V1, 1 - SD V2, or 3 - SDHC.
    */
@@ -205,7 +224,7 @@ class SdSpiCard {
    * the value false is returned for failure.
    */
   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.
    * \return The value true is returned for success and
    * the value false is returned for failure.
@@ -239,19 +258,19 @@ class SdSpiCard {
   uint8_t cardCommand(uint8_t cmd, uint32_t arg);
   bool readData(uint8_t* dst, size_t count);
   bool readRegister(uint8_t cmd, void* buf);
-  void chipSelectHigh();
-  void chipSelectLow();
-  void spiYield();
   void type(uint8_t value) {
     m_type = value;
   }
   bool waitNotBusy(uint16_t timeoutMillis);
   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() {
     return m_spi->receive();
@@ -265,10 +284,8 @@ class SdSpiCard {
   void spiSend(const uint8_t* buf, size_t n) {
     m_spi->send(buf, n);
   }
-  bool useSpiTransactions() {
-    return m_spi->useSpiTransactions();
-  }
   m_spi_t* m_spi;
+  bool m_selected;
   uint8_t m_chipSelectPin;
   uint8_t m_errorCode;
   uint8_t m_sckDivisor;
@@ -298,9 +315,13 @@ class Sd2Card : public SdSpiCard {
   bool init(uint8_t sckDivisor = 2, uint8_t chipSelectPin = SS) {
     return begin(chipSelectPin, sckDivisor);
   }
+
  private:
   bool begin(m_spi_t* spi, uint8_t chipSelectPin = SS,
              uint8_t sckDivisor = SPI_FULL_SPEED) {
+    (void)spi;
+    (void)chipSelectPin;
+    (void)sckDivisor;
     return false;
   }
   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;
 }
 //------------------------------------------------------------------------------
-void SdSpi::begin() {
+void SdSpi::begin(uint8_t chipSelectPin) {
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
   PIO_Configure(
     g_APinDescription[PIN_SPI_MOSI].pPort,
     g_APinDescription[PIN_SPI_MOSI].ulPinType,
@@ -132,7 +134,10 @@ static void spiDmaTX(const uint8_t* src, uint16_t count) {
 }
 //------------------------------------------------------------------------------
 //  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;
   Spi* pSpi = SPI0;
   //  disable SPI
@@ -147,6 +152,12 @@ void SdSpi::init(uint8_t sckDivisor) {
   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) {
   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
  */
-void SdSpi::begin() {
+void SdSpi::begin(uint8_t chipSelectPin) {
+  pinMode(chipSelectPin, OUTPUT);
+  digitalWrite(chipSelectPin, HIGH);
   SIM_SCGC6 |= SIM_SCGC6_SPI0;
 }
 //------------------------------------------------------------------------------
@@ -48,9 +50,11 @@ void SdSpi::begin() {
  * Initialize hardware SPI
  *
  */
-void SdSpi::init(uint8_t sckDivisor) {
+void SdSpi::beginTransaction(uint8_t sckDivisor) {
   uint32_t ctar, ctar0, ctar1;
-
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.beginTransaction(SPISettings());
+#endif  // #if ENABLE_SPI_TRANSACTIONS
   if (sckDivisor <= 2) {
     // 1/2 speed
     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
 //==============================================================================
 // Use standard SPI library if not KINETISK
-#include "SPI.h"
 /**
  * Initialize SPI pins.
  */
-void SdSpi::begin() {
+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 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.setDataMode(SPI_MODE0);
+#endif  // #if ENABLE_SPI_TRANSACTIONS
 #ifndef SPI_CLOCK_DIV128
   SPI.setClockDivider(divisor);
 #else  // SPI_CLOCK_DIV128
@@ -298,4 +307,10 @@ void SdSpi::send(const uint8_t* buf , size_t n) {
   }
 }
 #endif  // KINETISK
+//------------------------------------------------------------------------------
+void SdSpi::endTransaction() {
+#if ENABLE_SPI_TRANSACTIONS
+  SPI.endTransaction();
+#endif  // ENABLE_SPI_TRANSACTIONS
+}
 #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/>.
  */
 /**
- * @file
+ * @file 
  * @brief  Software SPI.
  *
  * @defgroup softSPI Software SPI
@@ -34,13 +34,13 @@
 #define nop asm volatile ("nop\n\t")
 //------------------------------------------------------------------------------
 /** Pin Mode for MISO is input.*/
-const bool MISO_MODE  = false;
+#define MISO_MODE INPUT
 /** Pullups disabled for MISO are disabled. */
-const bool MISO_LEVEL = false;
+#define MISO_LEVEL false
 /** Pin Mode for MOSI is output.*/
-const bool MOSI_MODE  = true;
+#define MOSI_MODE  OUTPUT
 /** Pin Mode for SCK is output. */
-const bool SCK_MODE   = true;
+#define SCK_MODE  OUTPUT
 //------------------------------------------------------------------------------
 /**
  * @class SoftSPI
@@ -110,13 +110,9 @@ class SoftSPI {
  private:
   //----------------------------------------------------------------------------
   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))
-  bool MODE_CPOL(uint8_t mode) {
-    return (mode & 2) != 0;
-  }
+  bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
   inline __attribute__((always_inline))
   void receiveBit(uint8_t bit, uint8_t* data) {
     if (MODE_CPHA(Mode)) {
@@ -125,10 +121,8 @@ class SoftSPI {
     nop;
     nop;
     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)) {
       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
     }
@@ -141,7 +135,7 @@ class SoftSPI {
     }
     fastDigitalWrite(MosiPin, data & (1 << bit));
     fastDigitalWrite(SckPin,
-                     MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
+      MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
     nop;
     nop;
     if (!MODE_CPHA(Mode)) {
@@ -156,10 +150,8 @@ class SoftSPI {
     }
     fastDigitalWrite(MosiPin, txData & (1 << bit));
     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)) {
       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

Some files were not shown because too many files changed in this diff