diff --git a/README.md b/README.md index 270046b1..0c6a98eb 100644 --- a/README.md +++ b/README.md @@ -3,37 +3,56 @@ file systems on SD/SDHC flash cards. 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. +Key changes: -For more information see the Manual installation section of this guide: +The SPI divisor has been replaced by SPISettings in the begin() call. -http://arduino.cc/en/Guide/Libraries - -A number of configuration options can be set by editing SdFatConfig.h -\#define macros. See the html documentation for details +``` +bool begin(uint8_t csPin = SS, SPISettings spiSettings = SPI_FULL_SPEED); +``` -Read changes.txt if you have used previous releases of this library. - -Please read the html documentation for this library. Start with -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. - -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 +Several macros have been defined for backward compatibility. ``` -#include +#define SD_SCK_MHZ(maxMhz) SPISettings(1000000UL*maxMhz, MSBFIRST, SPI_MODE0) +// SPI divisor constants +/** Set SCK to max possible rate. */ +#define SPI_FULL_SPEED SD_SCK_MHZ(50) +/** Set SCK rate to F_CPU/3 for Due */ +#define SPI_DIV3_SPEED SD_SCK_HZ(F_CPU/3) +/** Set SCK rate to F_CPU/4. */ +#define SPI_HALF_SPEED SD_SCK_HZ(F_CPU/4) +// ... ``` -with these two lines: +There are two new classes, SdFatEX and SdFatSoftSpiEX. + +Teensy 3.5/3.6 SDIO support has been added. Try the TeensySdioDemo example. +Many other example will work with Teensy SDIO if you use the SdFatSdio classes +and call begin with no parameters. ``` -#include "SdFat.h" -SdFat SD; + SdFatSdio sd; + + .... + + if (!sd.begin()) { + // Handle failure. + } + ``` +Please read changes.txt and the html documentation in the extras folder for more information. +Please report problems as issues. + +A number of configuration options can be set by editing SdFatConfig.h +define macros. See the html documentation for details + +Please read the html documentation for this library. Start with +html/index.html and read the Main Page. Next go to the Classes tab and +read the documentation for the classes SdFat, SdFatEX, SdBaseFile, +SdFile, File, StdioStream, ifstream, ofstream, and others. + Please continue by reading the html documentation. -Updated 19 Jul 2016 +Updated 26 Apr 2017 diff --git a/SdFat/examples/LowLatencyLogger/UserDataType.h b/SdFat/examples/LowLatencyLogger/UserDataType.h deleted file mode 100644 index 8e161e28..00000000 --- a/SdFat/examples/LowLatencyLogger/UserDataType.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef UserDataType_h -#define UserDataType_h -const uint8_t ADC_DIM = 4; -struct data_t { - unsigned long time; - unsigned short adc[ADC_DIM]; -}; -#endif // UserDataType_h diff --git a/SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino b/SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino deleted file mode 100644 index fd568c55..00000000 --- a/SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino +++ /dev/null @@ -1,77 +0,0 @@ -// Ported to SdFat from the native Arduino SD library example by Bill Greiman -// On the Ethernet Shield, CS is pin 4. SdFat handles setting SS -const int chipSelect = 4; -/* - SD card read/write - - This example shows how to read and write data to and from an SD card file - The circuit: - * SD card attached to SPI bus as follows: - ** MOSI - pin 11 - ** MISO - pin 12 - ** CLK - pin 13 - ** CS - pin 4 - - created Nov 2010 - by David A. Mellis - updated 2 Dec 2010 - by Tom Igoe - modified by Bill Greiman 11 Apr 2011 - This example code is in the public domain. - - */ -#include -#include "SdFat.h" -SdFat sd; -SdFile myFile; - -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 SdFat or print a detailed error message and halt - // Use half speed like the native library. - // change to SPI_FULL_SPEED for more performance. - if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // open the file for write at end like the Native SD library - if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) { - sd.errorHalt("opening test.txt for write failed"); - } - // if the file opened okay, write to it: - Serial.print("Writing to test.txt..."); - myFile.println("testing 1, 2, 3."); - - // close the file: - myFile.close(); - Serial.println("done."); - - // re-open the file for reading: - if (!myFile.open("test.txt", O_READ)) { - sd.errorHalt("opening test.txt for read failed"); - } - Serial.println("test.txt:"); - - // read from the file until there's nothing else in it: - int data; - while ((data = myFile.read()) >= 0) { - Serial.write(data); - } - // close the file: - myFile.close(); -} - -void loop() { - // nothing happens after setup -} - - diff --git a/SdFat/examples/ThreeCards/ThreeCards.ino b/SdFat/examples/ThreeCards/ThreeCards.ino deleted file mode 100644 index 8300360d..00000000 --- a/SdFat/examples/ThreeCards/ThreeCards.ino +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Example use of three SD cards. - */ -#include -#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 -// Using my fast custom SPI -SdFat sd1; -const uint8_t SD1_CS = 53; - -// SD2 is a Catalex shield on hardware SPI pins 50-52 -// Using the standard Arduino SPI library -SdFatLibSpi sd2; -const uint8_t SD2_CS = 4; - -// SD3 is a Adafruit data logging shield on pins 10-13 -// Using Software SPI -SdFatSoftSpi<12, 11, 13> sd3; -const uint8_t SD3_CS = 10; - -const uint8_t BUF_DIM = 100; -uint8_t buf[BUF_DIM]; - -const uint32_t FILE_SIZE = 1000000; -const uint16_t NWRITE = FILE_SIZE/BUF_DIM; -//------------------------------------------------------------------------------ -// print error msg, any SD error codes, and halt. -// store messages in flash -#define errorExit(msg) errorHalt(F(msg)) -#define initError(msg) initErrorHalt(F(msg)) -//------------------------------------------------------------------------------ -void list() { -// list current directory on all cards - Serial.println(F("------sd1-------")); - sd1.ls("/", LS_SIZE|LS_R); - Serial.println(F("------sd2-------")); - sd2.ls("/", LS_SIZE|LS_R); - Serial.println(F("------sd3-------")); - sd3.ls("/", LS_SIZE|LS_R); - Serial.println(F("---------------------")); -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - // Wait for USB Serial - while (!Serial) { - SysCall::yield(); - } - Serial.print(F("FreeStack: ")); - - Serial.println(FreeStack()); - - // fill buffer with known data - for (size_t i = 0; i < sizeof(buf); i++) { - buf[i] = i; - } - Serial.println(F("type any character to start")); - while (!Serial.available()) { - SysCall::yield(); - } - // disable sd2 while initializing sd1 - pinMode(SD2_CS, OUTPUT); - digitalWrite(SD2_CS, HIGH); - - // initialize the first card - if (!sd1.begin(SD1_CS)) { - sd1.initError("sd1:"); - } - - // initialize the second card - if (!sd2.begin(SD2_CS)) { - sd2.initError("sd2:"); - } - - // initialize the third card - if (!sd3.begin(SD3_CS)) { - sd3.initError("sd3:"); - } - - Serial.println(F("Cards OK - creating directories")); - - // create Dir1 on sd1 if it does not exist - if (!sd1.exists("/Dir1")) { - if (!sd1.mkdir("/Dir1")) { - sd1.errorExit("sd1.mkdir"); - } - } - // make /Dir1 the default directory for sd1 - if (!sd1.chdir("/Dir1")) { - sd1.errorExit("sd1.chdir"); - } - - // create Dir2 on sd2 if it does not exist - if (!sd2.exists("/Dir2")) { - if (!sd2.mkdir("/Dir2")) { - sd2.errorExit("sd2.mkdir"); - } - } - // make /Dir2 the default directory for sd2 - if (!sd2.chdir("/Dir2")) { - sd2.errorExit("sd2.chdir"); - } - - // create Dir3 on sd3 if it does not exist - if (!sd3.exists("/Dir3")) { - if (!sd3.mkdir("/Dir3")) { - sd2.errorExit("sd3.mkdir"); - } - } - // make /Dir3 the default directory for sd3 - if (!sd3.chdir("/Dir3")) { - sd3.errorExit("sd3.chdir"); - } - - Serial.println(F("Directories created - removing old files")); - - if (sd1.exists("TEST1.bin")) { - if (!sd1.remove("TEST1.bin")) { - sd1.errorExit("sd1.remove"); - } - } - if (sd2.exists("TEST2.bin")) { - if (!sd2.remove("TEST2.bin")) { - sd2.errorExit("sd2.remove"); - } - } - if (sd3.exists("TEST3.bin")) { - if (!sd3.remove("TEST3.bin")) { - sd2.errorExit("sd3.remove"); - } - } - Serial.println("Initial SD directories"); - list(); - - // create or open /Dir1/TEST1.bin and truncate it to zero length - SdFile file1; - if (!file1.open(&sd1, "TEST1.bin", O_RDWR | O_CREAT | O_TRUNC)) { - sd1.errorExit("file1"); - } - Serial.println(F("Writing SD1:/Dir1/TEST1.bin")); - - // write data to /Dir1/TEST1.bin on sd1 - for (uint16_t i = 0; i < NWRITE; i++) { - if (file1.write(buf, sizeof(buf)) != sizeof(buf)) { - sd1.errorExit("sd1.write"); - } - } - file1.sync(); - list(); - - // create or open /Dir2/TEST2.bin and truncate it to zero length - SdFile file2; - if (!file2.open(&sd2, "TEST2.bin", O_RDWR | O_CREAT | O_TRUNC)) { - sd2.errorExit("file2"); - } - Serial.println(F("Copying SD1:/Dir1/TEST1.bin to SD2::/Dir2/TEST2.bin")); - - // copy file1 to file2 - file1.rewind(); - - uint32_t t = millis(); - - while (1) { - int n = file1.read(buf, sizeof(buf)); - if (n < 0) { - sd1.errorExit("read1"); - } - if (n == 0) { - break; - } - if ((int)file2.write(buf, n) != n) { - sd2.errorExit("write3"); - } - } - t = millis() - t; - file2.sync(); - Serial.print(F("File size: ")); - Serial.println(file2.fileSize()); - Serial.print(F("Copy time: ")); - Serial.print(t); - Serial.println(F(" millis")); - list(); - - // create or open /Dir3/TEST3.bin and truncate it to zero length - SdFile file3; - if (!file3.open(&sd3, "TEST3.bin", O_RDWR | O_CREAT | O_TRUNC)) { - sd3.errorExit("file3"); - } - file2.rewind(); - Serial.println(F("Copying SD2:/Dir2/TEST2.bin to SD3:/Dir3/TEST3.bin")); - while (1) { - int n = file2.read(buf, sizeof(buf)); - if (n == 0) { - break; - } - if (n != sizeof(buf)) { - sd2.errorExit("read2"); - } - if ((int)file3.write(buf, n) != n) { - sd3.errorExit("write2"); - } - } - file3.sync(); - list(); - - // Verify content of file3 - file3.rewind(); - Serial.println(F("Verifying content of TEST3.bin")); - for (uint16_t i = 0; i < NWRITE; i++) { - if (file3.read(buf, sizeof(buf)) != sizeof(buf)) { - sd3.errorExit("sd3.read"); - } - for (size_t j = 0; j < sizeof(buf); j++) { - if (j != buf[j]) { - sd3.errorExit("Verify error"); - } - } - } - Serial.println(F("Done - Verify OK")); - file1.close(); - file2.close(); - file3.close(); -} -//------------------------------------------------------------------------------ -void loop() {} -#else // SD_SPI_CONFIGURATION >= 3 -#error SD_SPI_CONFIGURATION must be set to 3 in SdFat/SdFatConfig.h -#endif //SD_SPI_CONFIGURATION >= 3 \ No newline at end of file diff --git a/SdFat/library.properties b/SdFat/library.properties deleted file mode 100644 index 34d67aee..00000000 --- a/SdFat/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=SdFat -version=2015.4.26 -author= -maintainer= -sentence=FAT16/FAT32 file system for SD cards. -paragraph= -category=Uncategorized -url= -architectures=* diff --git a/SdFat/src/SdFat.cpp b/SdFat/src/SdFat.cpp deleted file mode 100644 index 7b962ad5..00000000 --- a/SdFat/src/SdFat.cpp +++ /dev/null @@ -1,100 +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 - * . - */ -#include "SdFat.h" -//------------------------------------------------------------------------------ -void SdFatBase::errorHalt(Print* pr) { - errorPrint(pr); - SysCall::halt(); -} -//------------------------------------------------------------------------------ -void SdFatBase::errorHalt(Print* pr, char const* msg) { - errorPrint(pr, msg); - SysCall::halt(); -} -//------------------------------------------------------------------------------ -void SdFatBase::errorPrint(Print* pr) { - if (!cardErrorCode()) { - return; - } - pr->print(F("SD errorCode: 0X")); - pr->print(cardErrorCode(), HEX); - pr->print(F(",0X")); - pr->println(cardErrorData(), HEX); -} -//------------------------------------------------------------------------------ -void SdFatBase::errorPrint(Print* pr, char const* msg) { - pr->print(F("error: ")); - pr->println(msg); - errorPrint(pr); -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorHalt(Print* pr) { - initErrorPrint(pr); - SysCall::halt(); -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorHalt(Print* pr, char const *msg) { - pr->println(msg); - initErrorHalt(pr); -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorPrint(Print* pr) { - if (cardErrorCode()) { - pr->println(F("Can't access SD card. Do not reformat.")); - if (cardErrorCode() == SD_CARD_ERROR_CMD0) { - pr->println(F("No card, wrong chip select pin, or SPI problem?")); - } - errorPrint(pr); - } else if (vol()->fatType() == 0) { - pr->println(F("Invalid format, reformat SD.")); - } else if (!vwd()->isOpen()) { - pr->println(F("Can't open root directory.")); - } else { - pr->println(F("No error found.")); - } -} -//------------------------------------------------------------------------------ -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) diff --git a/SdFat/src/SdFat.h b/SdFat/src/SdFat.h deleted file mode 100644 index 40a9b25e..00000000 --- a/SdFat/src/SdFat.h +++ /dev/null @@ -1,360 +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 - * . - */ -#ifndef SdFat_h -#define SdFat_h -/** - * \file - * \brief SdFat class - */ -#ifdef ARDUINO -#include "SdSpiCard/SdSpiCard.h" -#include "FatLib/FatLib.h" -#else // ARDUINO -#include "SdSpiCard.h" -#include "FatLib.h" -#endif // ARDUINO -//------------------------------------------------------------------------------ -/** SdFat version YYYYMMDD */ -#define SD_FAT_VERSION 20160719 -//============================================================================== -/** - * \class SdBaseFile - * \brief Class for backward compatibility. - */ -class SdBaseFile : public FatFile { - public: - SdBaseFile() {} - /** Create a file object and open it in the current working directory. - * - * \param[in] path A path for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a - * bitwise-inclusive OR of open flags. see - * FatFile::open(FatFile*, const char*, uint8_t). - */ - SdBaseFile(const char* path, uint8_t oflag) : FatFile(path, oflag) {} -}; -#if ENABLE_ARDUINO_FEATURES -/** - * \class SdFile - * \brief Class for backward compatibility. - */ -class SdFile : public PrintFile { - public: - SdFile() {} - /** Create a file object and open it in the current working directory. - * - * \param[in] path A path for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a - * bitwise-inclusive OR of open flags. see - * FatFile::open(FatFile*, const char*, uint8_t). - */ - SdFile(const char* path, uint8_t oflag) : PrintFile(path, oflag) {} -}; -#endif // #if ENABLE_ARDUINO_FEATURES -/** - * \class SdFatBase - * \brief Virtual base class for %SdFat library. - */ -class SdFatBase : public FatFileSystem { - public: - /** Initialize SD card and file system. - * \param[in] spi SPI object for the card. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(SdSpiCard::m_spi_t* spi, uint8_t csPin = SS, uint8_t divisor = 2) { - return m_sdCard.begin(spi, csPin, divisor) && - FatFileSystem::begin(); - } - /** \return Pointer to SD card object */ - SdSpiCard *card() { - return &m_sdCard; - } - /** %Print any SD error code to Serial and halt. */ - void errorHalt() { - errorHalt(&Serial); - } - /** %Print any SD error code and halt. - * - * \param[in] pr Print destination. - */ - void errorHalt(Print* pr); - /** %Print msg, any SD error code and halt. - * - * \param[in] msg Message to print. - */ - void errorHalt(char const* 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, char const* msg); - - /** %Print any SD error code to Serial */ - void errorPrint() { - errorPrint(&Serial); - } - /** %Print any SD error code. - * \param[in] pr Print device. - */ - void errorPrint(Print* pr); - /** %Print msg, any SD error code. - * - * \param[in] msg Message to print. - */ - void errorPrint(const char* 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, char const* msg); - - /** Diagnostic call to initialize FatFileSystem - use for - * diagnostic purposes only. - * \return true for success else false. - */ - bool fsBegin() { - return FatFileSystem::begin(); - } - /** %Print any SD error code and halt. */ - void initErrorHalt() { - initErrorHalt(&Serial); - } - /** %Print error details and halt after begin fails. - * - * \param[in] pr Print destination. - */ - void initErrorHalt(Print* pr); - /**Print message, error details, and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ - void initErrorHalt(char const *msg) { - initErrorHalt(&Serial, msg); - } - /**Print message, error details, and halt after SdFatBase::init() fails. - * \param[in] pr Print device. - * \param[in] msg Message to print. - */ - void initErrorHalt(Print* pr, char const *msg); - - /** Print error details after SdFat::init() fails. */ - void initErrorPrint() { - initErrorPrint(&Serial); - } - /** Print error details after SdFatBase::init() fails. - * - * \param[in] pr Print destination. - */ - void initErrorPrint(Print* pr); - /**Print message and error details and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ - void initErrorPrint(char const *msg) { - initErrorPrint(&Serial, msg); - } - /**Print message and error details and halt after SdFatBase::init() fails. - * - * \param[in] pr Print destination. - * \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. - */ - void initErrorPrint(const __FlashStringHelper* msg) { - initErrorPrint(&Serial, msg); - } - /**Print message and error details and halt after SdFatBase::init() fails. - * - * \param[in] pr Print destination. - * \param[in] msg Message to print. - */ - void initErrorPrint(Print* pr, const __FlashStringHelper* msg); -#endif // defined(ARDUINO) || defined(DOXYGEN) - - private: - uint8_t cardErrorCode() { - return m_sdCard.errorCode(); - } - uint8_t cardErrorData() { - return m_sdCard.errorData(); - } - 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); - } - SdSpiCard m_sdCard; -}; -//============================================================================== -/** - * \class SdFat - * \brief Main file system class for %SdFat library. - */ -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. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(uint8_t csPin = SS, uint8_t divisor = 2) { - return SdFatBase::begin(&m_spi, csPin, divisor); - } - /** Diagnostic call to initialize SD card - use for diagnostic purposes only. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) { - return card()->begin(&m_spi, csPin, divisor); - } - - private: - SpiDefault_t m_spi; -}; -//============================================================================== -#if SD_SPI_CONFIGURATION >= 3 || defined(DOXYGEN) -/** - * \class SdFatLibSpi - * \brief SdFat class using the standard Arduino SPI library. - */ -class SdFatLibSpi: public SdFatBase { - public: - /** Initialize SD card and file system. - * - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(uint8_t csPin = SS, uint8_t divisor = 2) { - return SdFatBase::begin(&m_spi, csPin, divisor); - } - /** Diagnostic call to initialize SD card - use for diagnostic purposes only. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) { - return card()->begin(&m_spi, csPin, divisor); - } - - private: - SdSpiLib m_spi; -}; -//============================================================================== -/** - * \class SdFatSoftSpi - * \brief SdFat class using software SPI. - */ -template -class SdFatSoftSpi : public SdFatBase { - public: - /** Initialize SD card and file system. - * - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(uint8_t csPin = SS, uint8_t divisor = 2) { - return SdFatBase::begin(&m_spi, csPin, divisor); - } - /** Diagnostic call to initialize SD card - use for diagnostic purposes only. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) { - return card()->begin(&m_spi, csPin, divisor); - } - - private: - SdSpiSoft m_spi; -}; -#endif /// SD_SPI_CONFIGURATION >= 3 || defined(DOXYGEN) -#endif // SdFat_h diff --git a/SdFat/src/SdFatUtil.h b/SdFat/src/SdFatUtil.h deleted file mode 100644 index ee36bfdf..00000000 --- a/SdFat/src/SdFatUtil.h +++ /dev/null @@ -1,35 +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 - * . - */ -#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 diff --git a/SdFat/src/SdSpiCard/SdSpi.h b/SdFat/src/SdSpiCard/SdSpi.h deleted file mode 100644 index 57ea1843..00000000 --- a/SdFat/src/SdSpiCard/SdSpi.h +++ /dev/null @@ -1,411 +0,0 @@ -/* 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 - * . - */ -/** -* \file -* \brief SdSpi class for V2 SD/SDHC cards -*/ -#ifndef SdSpi_h -#define SdSpi_h -#include "SystemInclude.h" -#include "SdFatConfig.h" -//------------------------------------------------------------------------------ -/** - * \class SdSpiBase - * \brief Virtual SPI class for access to SD and SDHC flash memory cards. - */ -class SdSpiBase { - public: - /** 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 beginTransaction(uint8_t divisor); - /** - * End SPI transaction. - */ - virtual void endTransaction(); - /** Receive a byte. - * - * \return The byte. - */ - virtual uint8_t receive() = 0; - /** 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. - */ - virtual uint8_t receive(uint8_t* buf, size_t n) = 0; - /** Send a byte. - * - * \param[in] data Byte to send - */ - virtual void send(uint8_t data) = 0; - /** Send multiple bytes. - * - * \param[in] buf Buffer for data to be sent. - * \param[in] n Number of bytes to send. - */ - virtual void send(const uint8_t* buf, size_t n) = 0; -}; -//------------------------------------------------------------------------------ -/** - * \class SdSpi - * \brief SPI class for access to SD and SDHC flash memory cards. - */ -#if SD_SPI_CONFIGURATION >= 3 -class SdSpi : public SdSpiBase { -#else // SD_SPI_CONFIGURATION >= 3 -class SdSpi { -#endif // SD_SPI_CONFIGURATION >= 3 - public: - /** 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 beginTransaction(uint8_t divisor); - /** - * End SPI transaction - */ - void endTransaction(); - /** Receive a byte. - * - * \return The byte. - */ - uint8_t receive(); - /** 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 receive(uint8_t* buf, size_t n); - /** Send a byte. - * - * \param[in] data Byte to send - */ - void send(uint8_t data); - /** Send multiple bytes. - * - * \param[in] buf Buffer for data to be sent. - * \param[in] n Number of bytes to send. - */ - void send(const uint8_t* buf, size_t n); - /** \return true - uses SPI transactions */ -#if IMPLEMENT_SPI_INTERFACE_SELECTION - void setSpiIf(uint8_t spiIf) { - m_spiIf = spiIf; - } - private: - uint8_t m_spiIf; -#endif // IMPLEMENT_SPI_INTERFACE_SELECTION -}; -//------------------------------------------------------------------------------ -/** - * \class SdSpiLib - * \brief Arduino SPI library class for access to SD and SDHC flash - * memory cards. - */ -#if SD_SPI_CONFIGURATION >= 3 -class SdSpiLib : public SdSpiBase { -#else // SD_SPI_CONFIGURATION >= 3 -class SdSpiLib { -#endif // SD_SPI_CONFIGURATION >= 3 - public: - /** Initialize the SPI bus. - * - * \param[in] chipSelectPin SD card chip select pin. - */ - 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 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 - 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; - } - 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. - * - * \return The byte. - */ - uint8_t 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 receive(uint8_t* buf, size_t n) { - for (size_t i = 0; i < n; i++) { - buf[i] = SPI.transfer(0XFF); - } - return 0; - } - /** Send a byte. - * - * \param[in] b Byte to send - */ - void 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 send(const uint8_t* buf , size_t n) { - for (size_t i = 0; i < n; i++) { - SPI.transfer(buf[i]); - } - } -}; -//------------------------------------------------------------------------------ -#if SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN) -#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. - */ -template -class SdSpiSoft : public SdSpiBase { - public: - /** Initialize the SPI bus. - * - * \param[in] chipSelectPin SD card chip select pin. - */ - 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 beginTransaction(uint8_t divisor) { - (void)divisor; - } - /** - * End SPI transaction - dummy for soft SPI - */ - void endTransaction() {} - /** Receive a byte. - * - * \return The byte. - */ - uint8_t receive() { - return m_spi.receive(); - } - /** 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 receive(uint8_t* buf, size_t n) { - for (size_t i = 0; i < n; i++) { - buf[i] = receive(); - } - return 0; - } - /** Send a byte. - * - * \param[in] data Byte to send - */ - void send(uint8_t data) { - m_spi.send(data); - } - /** Send multiple bytes. - * - * \param[in] buf Buffer for data to be sent. - * \param[in] n Number of bytes to send. - */ - void send(const uint8_t* buf , size_t n) { - for (size_t i = 0; i < n; i++) { - send(buf[i]); - } - } - - private: - SoftSPI m_spi; -}; -#endif // SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN) -//------------------------------------------------------------------------------ -#if SD_SPI_CONFIGURATION == 2 -/** Default is software SPI. */ -typedef SdSpiSoft -SpiDefault_t; -#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(uint8_t chipSelectPin) { -#ifdef __AVR_ATmega328P__ - // Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi. - PORTB |= 1 << 2; // SS high - DDRB |= 1 << 2; // SS output mode - DDRB |= 1 << 3; // MOSI output mode - DDRB |= 1 << 5; // SCK output mode -#else // __AVR_ATmega328P__ - - // set SS high - may be chip select for another SPI device - digitalWrite(SS, HIGH); - - // SS must be in output mode even it is not chip select - pinMode(SS, OUTPUT); - pinMode(MOSI, OUTPUT); - pinMode(SCK, OUTPUT); -#endif // __AVR_ATmega328P__ - pinMode(chipSelectPin, OUTPUT); - digitalWrite(chipSelectPin, HIGH); -} -//------------------------------------------------------------------------------ -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; - - // See AVR processor documentation. - for (; divisor > b && r < 7; b <<= 1, r += r < 5 ? 1 : 2) {} - SPCR = (1 << SPE) | (1 << MSTR) | (r >> 1); - 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))) {} - return SPDR; -} -//------------------------------------------------------------------------------ -inline uint8_t SdSpi::receive(uint8_t* buf, size_t n) { - if (n-- == 0) { - return 0; - } - SPDR = 0XFF; - for (size_t i = 0; i < n; i++) { - while (!(SPSR & (1 << SPIF))) {} - uint8_t b = SPDR; - SPDR = 0XFF; - buf[i] = b; - } - while (!(SPSR & (1 << SPIF))) {} - buf[n] = SPDR; - return 0; -} -//------------------------------------------------------------------------------ -inline void SdSpi::send(uint8_t data) { - SPDR = data; - while (!(SPSR & (1 << SPIF))) {} -} -//------------------------------------------------------------------------------ -inline void SdSpi::send(const uint8_t* buf , size_t n) { - if (n == 0) { - return; - } - SPDR = buf[0]; - if (n > 1) { - uint8_t b = buf[1]; - size_t i = 2; - while (1) { - while (!(SPSR & (1 << SPIF))) {} - SPDR = b; - if (i == n) { - break; - } - b = buf[i++]; - } - } - while (!(SPSR & (1 << SPIF))) {} -} -#endif // __AVR__ -#endif // SdSpi_h diff --git a/SdFat/src/SdSpiCard/SdSpiParticle.cpp b/SdFat/src/SdSpiCard/SdSpiParticle.cpp deleted file mode 100644 index 4fdca4f9..00000000 --- a/SdFat/src/SdSpiCard/SdSpiParticle.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* 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 - * . - */ -#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(buf), 0, n, - SD_SPI_DMA_TransferComplete_Callback); - - while (!SPI_DMA_TransferCompleted) {} - if (bugDelay) { - delayMicroseconds(bugDelay); - } -} -#endif // defined(PLATFORM_ID) diff --git a/SdFat/src/SystemInclude.h b/SdFat/src/SystemInclude.h deleted file mode 100644 index 3ee341dc..00000000 --- a/SdFat/src/SystemInclude.h +++ /dev/null @@ -1,29 +0,0 @@ -/* 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 - * . - */ -#ifndef SystemInclude_h -#define SystemInclude_h -#if defined(ARDUINO) -#include "FatLib/SysCall.h" -#elif defined(PLATFORM_ID) // Only defined if a Particle device -#include "SysCall.h" -#else // System type -#error Unknown System. -#endif // System type -#endif // SystemInclude_h diff --git a/SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino b/examples/#attic/AnalogLogger/AnalogLogger.ino similarity index 96% rename from SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino rename to examples/#attic/AnalogLogger/AnalogLogger.ino index 9ee6b408..e846d534 100644 --- a/SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino +++ b/examples/#attic/AnalogLogger/AnalogLogger.ino @@ -97,8 +97,9 @@ void setup() { cout << now << endl; #endif // USE_DS1307 - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(SD_CHIP_SELECT, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino b/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino similarity index 92% rename from SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino rename to examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino index 3c876d4d..0212d3ba 100644 --- a/SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino +++ b/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino @@ -4,6 +4,8 @@ #include #include "SdFat.h" +const uint8_t chipSelect = SS; + SdFat sd; SdFile file; @@ -24,7 +26,7 @@ void setup() { while (!Serial.available()) { SysCall::yield(); } - if (!sd.begin()) { + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { Serial.println("begin failed"); return; } diff --git a/SdFat/examples/#attic/HelloWorld/HelloWorld.ino b/examples/#attic/HelloWorld/HelloWorld.ino similarity index 100% rename from SdFat/examples/#attic/HelloWorld/HelloWorld.ino rename to examples/#attic/HelloWorld/HelloWorld.ino diff --git a/SdFat/examples/#attic/MiniSerial/MiniSerial.ino b/examples/#attic/MiniSerial/MiniSerial.ino similarity index 100% rename from SdFat/examples/#attic/MiniSerial/MiniSerial.ino rename to examples/#attic/MiniSerial/MiniSerial.ino diff --git a/SdFat/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino b/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino similarity index 100% rename from SdFat/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino rename to examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino diff --git a/SdFat/examples/#attic/SD_Size/SD_Size.ino b/examples/#attic/SD_Size/SD_Size.ino similarity index 100% rename from SdFat/examples/#attic/SD_Size/SD_Size.ino rename to examples/#attic/SD_Size/SD_Size.ino diff --git a/SdFat/examples/#attic/SdFatSize/SdFatSize.ino b/examples/#attic/SdFatSize/SdFatSize.ino similarity index 100% rename from SdFat/examples/#attic/SdFatSize/SdFatSize.ino rename to examples/#attic/SdFatSize/SdFatSize.ino diff --git a/SdFat/examples/#attic/StreamParseInt/StreamParseInt.ino b/examples/#attic/StreamParseInt/StreamParseInt.ino similarity index 97% rename from SdFat/examples/#attic/StreamParseInt/StreamParseInt.ino rename to examples/#attic/StreamParseInt/StreamParseInt.ino index 15cc147a..2da1f7c6 100644 --- a/SdFat/examples/#attic/StreamParseInt/StreamParseInt.ino +++ b/examples/#attic/StreamParseInt/StreamParseInt.ino @@ -5,7 +5,7 @@ SdFat SD; // SD card chip select pin - Modify the value of csPin for your SD module. -const uint8_t csPin = 10; +const uint8_t csPin = SS; File file; //------------------------------------------------------------------------------ diff --git a/SdFat/examples/#attic/append/append.ino b/examples/#attic/append/append.ino similarity index 90% rename from SdFat/examples/#attic/append/append.ino rename to examples/#attic/append/append.ino index 68f8d9e8..6ced4df5 100644 --- a/SdFat/examples/#attic/append/append.ino +++ b/examples/#attic/append/append.ino @@ -36,9 +36,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/#attic/average/average.ino b/examples/#attic/average/average.ino similarity index 90% rename from SdFat/examples/#attic/average/average.ino rename to examples/#attic/average/average.ino index 562a97c7..01be276c 100644 --- a/SdFat/examples/#attic/average/average.ino +++ b/examples/#attic/average/average.ino @@ -65,9 +65,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/#attic/benchSD/benchSD.ino b/examples/#attic/benchSD/benchSD.ino similarity index 100% rename from SdFat/examples/#attic/benchSD/benchSD.ino rename to examples/#attic/benchSD/benchSD.ino diff --git a/SdFat/examples/#attic/bufstream/bufstream.ino b/examples/#attic/bufstream/bufstream.ino similarity index 100% rename from SdFat/examples/#attic/bufstream/bufstream.ino rename to examples/#attic/bufstream/bufstream.ino diff --git a/SdFat/examples/#attic/cin_cout/cin_cout.ino b/examples/#attic/cin_cout/cin_cout.ino similarity index 100% rename from SdFat/examples/#attic/cin_cout/cin_cout.ino rename to examples/#attic/cin_cout/cin_cout.ino diff --git a/SdFat/examples/#attic/eventlog/eventlog.ino b/examples/#attic/eventlog/eventlog.ino similarity index 88% rename from SdFat/examples/#attic/eventlog/eventlog.ino rename to examples/#attic/eventlog/eventlog.ino index 5a64f4bf..43d701c3 100644 --- a/SdFat/examples/#attic/eventlog/eventlog.ino +++ b/examples/#attic/eventlog/eventlog.ino @@ -47,9 +47,9 @@ void setup() { } 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino b/examples/#attic/fgetsRewrite/fgetsRewrite.ino similarity index 92% rename from SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino rename to examples/#attic/fgetsRewrite/fgetsRewrite.ino index 285d5656..622d1e5b 100644 --- a/SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino +++ b/examples/#attic/fgetsRewrite/fgetsRewrite.ino @@ -95,9 +95,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/#attic/readlog/readlog.ino b/examples/#attic/readlog/readlog.ino similarity index 84% rename from SdFat/examples/#attic/readlog/readlog.ino rename to examples/#attic/readlog/readlog.ino index 738e733e..31e9d06f 100644 --- a/SdFat/examples/#attic/readlog/readlog.ino +++ b/examples/#attic/readlog/readlog.ino @@ -22,9 +22,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/#attic/readme.txt b/examples/#attic/readme.txt similarity index 100% rename from SdFat/examples/#attic/readme.txt rename to examples/#attic/readme.txt diff --git a/SdFat/examples/AnalogBinLogger/AnalogBinLogger.h b/examples/AnalogBinLogger/AnalogBinLogger.h similarity index 100% rename from SdFat/examples/AnalogBinLogger/AnalogBinLogger.h rename to examples/AnalogBinLogger/AnalogBinLogger.h diff --git a/SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino b/examples/AnalogBinLogger/AnalogBinLogger.ino similarity index 98% rename from SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino rename to examples/AnalogBinLogger/AnalogBinLogger.ino index 504b07ed..48c1a61d 100644 --- a/SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino +++ b/examples/AnalogBinLogger/AnalogBinLogger.ino @@ -256,12 +256,7 @@ ISR(TIMER1_COMPB_vect) { } //============================================================================== // Error messages stored in flash. -#define error(msg) errorFlash(F(msg)) -//------------------------------------------------------------------------------ -void errorFlash(const __FlashStringHelper* msg) { - sd.errorPrint(msg); - fatalBlink(); -} +#define error(msg) {sd.errorPrint(F(msg));fatalBlink();} //------------------------------------------------------------------------------ // void fatalBlink() { @@ -625,8 +620,7 @@ void logData() { // Create new file. Serial.println(F("Creating new file")); binFile.close(); - if (!binFile.createContiguous(sd.vwd(), - TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { + if (!binFile.createContiguous(TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { error("createContiguous failed"); } // Get the address of the file on the SD. @@ -783,8 +777,9 @@ void setup(void) { Serial.print(F("FreeStack: ")); Serial.println(FreeStack()); - // initialize file system. - if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) { sd.initErrorPrint(); fatalBlink(); } diff --git a/SdFat/examples/directoryFunctions/directoryFunctions.ino b/examples/DirectoryFunctions/DirectoryFunctions.ino similarity index 93% rename from SdFat/examples/directoryFunctions/directoryFunctions.ino rename to examples/DirectoryFunctions/DirectoryFunctions.ino index b9331088..13ffc7ec 100644 --- a/SdFat/examples/directoryFunctions/directoryFunctions.ino +++ b/examples/DirectoryFunctions/DirectoryFunctions.ino @@ -5,7 +5,7 @@ #include "SdFat.h" // SD card chip select pin. -const uint8_t SD_CHIP_SELECT = SS; +const uint8_t chipSelect = SS; //------------------------------------------------------------------------------ // File system object. @@ -40,9 +40,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } if (sd.exists("Folder1") diff --git a/SdFat/examples/LongFileName/LongFileName.ino b/examples/LongFileName/LongFileName.ino similarity index 93% rename from SdFat/examples/LongFileName/LongFileName.ino rename to examples/LongFileName/LongFileName.ino index a6446b24..a3fb27ae 100644 --- a/SdFat/examples/LongFileName/LongFileName.ino +++ b/examples/LongFileName/LongFileName.ino @@ -31,7 +31,9 @@ void setup() { "You can use test files located in\r\n" "SdFat/examples/LongFileName/testFiles")); - if (!sd.begin(SD_CS_PIN)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } Serial.print(F("FreeStack: ")); diff --git a/SdFat/examples/LongFileName/testFiles/A long name can be 255 characters.txt b/examples/LongFileName/testFiles/A long name can be 255 characters.txt similarity index 100% rename from SdFat/examples/LongFileName/testFiles/A long name can be 255 characters.txt rename to examples/LongFileName/testFiles/A long name can be 255 characters.txt diff --git a/SdFat/examples/LongFileName/testFiles/LFN,NAME.TXT b/examples/LongFileName/testFiles/LFN,NAME.TXT similarity index 100% rename from SdFat/examples/LongFileName/testFiles/LFN,NAME.TXT rename to examples/LongFileName/testFiles/LFN,NAME.TXT diff --git a/SdFat/examples/LongFileName/testFiles/MIXCASE.txt b/examples/LongFileName/testFiles/MIXCASE.txt similarity index 100% rename from SdFat/examples/LongFileName/testFiles/MIXCASE.txt rename to examples/LongFileName/testFiles/MIXCASE.txt diff --git a/SdFat/examples/LongFileName/testFiles/Not_8_3.txt b/examples/LongFileName/testFiles/Not_8_3.txt similarity index 100% rename from SdFat/examples/LongFileName/testFiles/Not_8_3.txt rename to examples/LongFileName/testFiles/Not_8_3.txt diff --git a/SdFat/examples/LongFileName/testFiles/OK%83.TXT b/examples/LongFileName/testFiles/OK%83.TXT similarity index 100% rename from SdFat/examples/LongFileName/testFiles/OK%83.TXT rename to examples/LongFileName/testFiles/OK%83.TXT diff --git a/SdFat/examples/LongFileName/testFiles/STD_8_3.TXT b/examples/LongFileName/testFiles/STD_8_3.TXT similarity index 100% rename from SdFat/examples/LongFileName/testFiles/STD_8_3.TXT rename to examples/LongFileName/testFiles/STD_8_3.TXT diff --git a/SdFat/examples/LongFileName/testFiles/With Blank.txt b/examples/LongFileName/testFiles/With Blank.txt similarity index 100% rename from SdFat/examples/LongFileName/testFiles/With Blank.txt rename to examples/LongFileName/testFiles/With Blank.txt diff --git a/SdFat/examples/LongFileName/testFiles/With.Two dots.txt b/examples/LongFileName/testFiles/With.Two dots.txt similarity index 100% rename from SdFat/examples/LongFileName/testFiles/With.Two dots.txt rename to examples/LongFileName/testFiles/With.Two dots.txt diff --git a/SdFat/examples/LongFileName/testFiles/lower.txt b/examples/LongFileName/testFiles/lower.txt similarity index 100% rename from SdFat/examples/LongFileName/testFiles/lower.txt rename to examples/LongFileName/testFiles/lower.txt diff --git a/SdFat/examples/LongFileName/testFiles/mixed.TXT b/examples/LongFileName/testFiles/mixed.TXT similarity index 100% rename from SdFat/examples/LongFileName/testFiles/mixed.TXT rename to examples/LongFileName/testFiles/mixed.TXT diff --git a/SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino b/examples/LowLatencyLogger/LowLatencyLogger.ino similarity index 61% rename from SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino rename to examples/LowLatencyLogger/LowLatencyLogger.ino index 0a3d0b0a..35cd3821 100644 --- a/SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino +++ b/examples/LowLatencyLogger/LowLatencyLogger.ino @@ -9,66 +9,47 @@ * * If your SD card has a long write latency, it may be necessary to use * slower sample rates. Using a Mega Arduino helps overcome latency - * problems since 13 512 byte buffers will be used. + * problems since 12 512 byte buffers will be used. * * Data is written to the file using a SD multiple block write command. */ #include #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. - -// Acquire a data record. -void acquireData(data_t* data) { - data->time = micros(); - for (int i = 0; i < ADC_DIM; i++) { - data->adc[i] = analogRead(i); - } -} - -// Print a data record. -void printData(Print* pr, data_t* data) { - pr->print(data->time - startMicros); - for (int i = 0; i < ADC_DIM; i++) { - pr->write(','); - pr->print(data->adc[i]); - } - pr->println(); -} +#include "UserTypes.h" -// Print data header. -void printHeader(Print* pr) { - pr->print(F("time")); - for (int i = 0; i < ADC_DIM; i++) { - pr->print(F(",adc")); - pr->print(i); - } - pr->println(); -} +#ifdef __AVR_ATmega328P__ +#include "MinimumSerial.h" +MinimumSerial MinSerial; +#define Serial MinSerial +#endif // __AVR_ATmega328P__ //============================================================================== // Start of configuration constants. //============================================================================== +// Abort run on an overrun. Data before the overrun will be saved. +#define ABORT_ON_OVERRUN 1 +//------------------------------------------------------------------------------ //Interval between data records in microseconds. const uint32_t LOG_INTERVAL_USEC = 2000; //------------------------------------------------------------------------------ +// Set USE_SHARED_SPI non-zero for use of an SPI sensor. +// May not work for some cards. +#ifndef USE_SHARED_SPI +#define USE_SHARED_SPI 0 +#endif // USE_SHARED_SPI +//------------------------------------------------------------------------------ // Pin definitions. // // SD chip select pin. 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. +// The led blinks for fatal errors. The led goes on solid for +// overrun errors and logging continues unless ABORT_ON_OVERRUN +// is non-zero. +#ifdef ERROR_LED_PIN #undef ERROR_LED_PIN +#endif // ERROR_LED_PIN const int8_t ERROR_LED_PIN = -1; //------------------------------------------------------------------------------ // File definitions. @@ -78,49 +59,51 @@ const int8_t ERROR_LED_PIN = -1; // This file is flash erased using special SD commands. The file will be // truncated if logging is stopped early. const uint32_t FILE_BLOCK_COUNT = 256000; - -// log file base name. Must be six characters or less. +// +// log file base name if not defined in UserTypes.h +#ifndef FILE_BASE_NAME #define FILE_BASE_NAME "data" +#endif // FILE_BASE_NAME //------------------------------------------------------------------------------ // Buffer definitions. // -// The logger will use SdFat's buffer plus BUFFER_BLOCK_COUNT additional +// The logger will use SdFat's buffer plus BUFFER_BLOCK_COUNT-1 additional // buffers. // #ifndef RAMEND -// Assume ARM. Use total of nine 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 8; +// Assume ARM. Use total of ten 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 10; // #elif RAMEND < 0X8FF #error Too little SRAM // #elif RAMEND < 0X10FF // Use total of two 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 1; +const uint8_t BUFFER_BLOCK_COUNT = 2; // #elif RAMEND < 0X20FF -// Use total of five 512 byte buffers. +// Use total of four 512 byte buffers. const uint8_t BUFFER_BLOCK_COUNT = 4; // #else // RAMEND -// Use total of 13 512 byte buffers. +// Use total of 12 512 byte buffers. const uint8_t BUFFER_BLOCK_COUNT = 12; #endif // RAMEND //============================================================================== // End of configuration constants. //============================================================================== // Temporary log file. Will be deleted if a reset or power failure occurs. -#define TMP_FILE_NAME "tmp_log.bin" +#define TMP_FILE_NAME FILE_BASE_NAME "##.bin" -// Size of file base name. Must not be larger than six. +// Size of file base name. const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1; +const uint8_t FILE_NAME_DIM = BASE_NAME_SIZE + 7; +char binName[FILE_NAME_DIM] = FILE_BASE_NAME "00.bin"; SdFat sd; SdBaseFile binFile; -char binName[13] = FILE_BASE_NAME "00.bin"; - // Number of data records in a block. const uint16_t DATA_DIM = (512 - 4)/sizeof(data_t); @@ -133,33 +116,14 @@ struct block_t { data_t data[DATA_DIM]; uint8_t fill[FILL_DIM]; }; - -const uint8_t QUEUE_DIM = BUFFER_BLOCK_COUNT + 2; - -block_t* emptyQueue[QUEUE_DIM]; -uint8_t emptyHead; -uint8_t emptyTail; - -block_t* fullQueue[QUEUE_DIM]; -uint8_t fullHead; -uint8_t fullTail; - -// Advance queue index. -inline uint8_t queueNext(uint8_t ht) { - return ht < (QUEUE_DIM - 1) ? ht + 1 : 0; -} //============================================================================== // Error messages stored in flash. -#define error(msg) errorFlash(F(msg)) -//------------------------------------------------------------------------------ -void errorFlash(const __FlashStringHelper* msg) { - sd.errorPrint(msg); - fatalBlink(); -} +#define error(msg) {sd.errorPrint(&Serial, F(msg));fatalBlink();} //------------------------------------------------------------------------------ // void fatalBlink() { while (true) { + SysCall::yield(); if (ERROR_LED_PIN >= 0) { digitalWrite(ERROR_LED_PIN, HIGH); delay(200); @@ -168,7 +132,49 @@ void fatalBlink() { } } } -//============================================================================== +//------------------------------------------------------------------------------ +// read data file and check for overruns +void checkOverrun() { + bool headerPrinted = false; + block_t block; + uint32_t bn = 0; + + if (!binFile.isOpen()) { + Serial.println(); + Serial.println(F("No current binary file")); + return; + } + binFile.rewind(); + Serial.println(); + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + Serial.println(F("Checking overrun errors - type any character to stop")); + while (binFile.read(&block, 512) == 512) { + if (block.count == 0) { + break; + } + if (block.overrun) { + if (!headerPrinted) { + Serial.println(); + Serial.println(F("Overruns:")); + Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount")); + headerPrinted = true; + } + Serial.print(bn); + Serial.print(','); + Serial.print(binFile.firstBlock() + bn); + Serial.print(','); + Serial.println(block.overrun); + } + bn++; + } + if (!headerPrinted) { + Serial.println(F("No errors found")); + } else { + Serial.println(F("Done")); + } +} +//----------------------------------------------------------------------------- // Convert binary file to csv file. void binaryToCsv() { uint8_t lastPct = 0; @@ -176,14 +182,17 @@ void binaryToCsv() { uint32_t t0 = millis(); uint32_t syncCluster = 0; SdFile csvFile; - char csvName[13]; + char csvName[FILE_NAME_DIM]; if (!binFile.isOpen()) { Serial.println(); Serial.println(F("No current binary file")); return; } - binFile.rewind(); + Serial.println(); + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + // Create a new csvFile. strcpy(csvName, binName); strcpy(&csvName[BASE_NAME_SIZE + 3], "csv"); @@ -191,7 +200,7 @@ void binaryToCsv() { if (!csvFile.open(csvName, O_WRITE | O_CREAT | O_TRUNC)) { error("open csvFile failed"); } - Serial.println(); + binFile.rewind(); Serial.print(F("Writing: ")); Serial.print(csvName); Serial.println(F(" - type any character to stop")); @@ -199,7 +208,7 @@ void binaryToCsv() { uint32_t tPct = millis(); while (!Serial.available() && binFile.read(&block, 512) == 512) { uint16_t i; - if (block.count == 0) { + if (block.count == 0 || block.count > DATA_DIM) { break; } if (block.overrun) { @@ -231,48 +240,42 @@ void binaryToCsv() { Serial.print(0.001*(millis() - t0)); Serial.println(F(" Seconds")); } -//------------------------------------------------------------------------------ -// read data file and check for overruns -void checkOverrun() { - bool headerPrinted = false; - block_t block; +//----------------------------------------------------------------------------- +void createBinFile() { + // max number of blocks to erase per erase call + const uint32_t ERASE_SIZE = 262144L; uint32_t bgnBlock, endBlock; - uint32_t bn = 0; - - if (!binFile.isOpen()) { - Serial.println(); - Serial.println(F("No current binary file")); - return; + + // Delete old tmp file. + if (sd.exists(TMP_FILE_NAME)) { + Serial.println(F("Deleting tmp file " TMP_FILE_NAME)); + if (!sd.remove(TMP_FILE_NAME)) { + error("Can't remove tmp file"); + } } + // Create new file. + Serial.println(F("\nCreating new file")); + binFile.close(); + if (!binFile.createContiguous(TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { + error("createContiguous failed"); + } + // Get the address of the file on the SD. if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { error("contiguousRange failed"); } - binFile.rewind(); - Serial.println(); - Serial.println(F("Checking overrun errors - type any character to stop")); - while (binFile.read(&block, 512) == 512) { - if (block.count == 0) { - break; + // Flash erase all data in the file. + Serial.println(F("Erasing all data")); + uint32_t bgnErase = bgnBlock; + uint32_t endErase; + while (bgnErase < endBlock) { + endErase = bgnErase + ERASE_SIZE; + if (endErase > endBlock) { + endErase = endBlock; } - if (block.overrun) { - if (!headerPrinted) { - Serial.println(); - Serial.println(F("Overruns:")); - Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount")); - headerPrinted = true; - } - Serial.print(bn); - Serial.print(','); - Serial.print(bgnBlock + bn); - Serial.print(','); - Serial.println(block.overrun); + if (!sd.card()->erase(bgnErase, endErase)) { + error("erase failed"); } - bn++; - } - if (!headerPrinted) { - Serial.println(F("No errors found")); - } else { - Serial.println(F("Done")); + bgnErase = endErase + 1; } } //------------------------------------------------------------------------------ @@ -305,123 +308,105 @@ void dumpData() { } //------------------------------------------------------------------------------ // log data -// max number of blocks to erase per erase call -uint32_t const ERASE_SIZE = 262144L; void logData() { - uint32_t bgnBlock, endBlock; - - // Allocate extra buffer space. - block_t block[BUFFER_BLOCK_COUNT]; - block_t* curBlock = 0; - Serial.println(); - - // Find unused file name. - if (BASE_NAME_SIZE > 6) { - error("FILE_BASE_NAME too long"); - } - while (sd.exists(binName)) { - if (binName[BASE_NAME_SIZE + 1] != '9') { - binName[BASE_NAME_SIZE + 1]++; - } else { - binName[BASE_NAME_SIZE + 1] = '0'; - if (binName[BASE_NAME_SIZE] == '9') { - error("Can't create file name"); - } - binName[BASE_NAME_SIZE]++; + createBinFile(); + recordBinFile(); + renameBinFile(); +} +//------------------------------------------------------------------------------ +void openBinFile() { + char name[FILE_NAME_DIM]; + strcpy(name, binName); + Serial.println(F("\nEnter two digit version")); + Serial.write(name, BASE_NAME_SIZE); + for (int i = 0; i < 2; i++) { + while (!Serial.available()) { + SysCall::yield(); } - } - // Delete old tmp file. - if (sd.exists(TMP_FILE_NAME)) { - Serial.println(F("Deleting tmp file")); - if (!sd.remove(TMP_FILE_NAME)) { - error("Can't remove tmp file"); + char c = Serial.read(); + Serial.write(c); + if (c < '0' || c > '9') { + Serial.println(F("\nInvalid digit")); + return; } + name[BASE_NAME_SIZE + i] = c; } - // Create new file. - Serial.println(F("Creating new file")); - binFile.close(); - if (!binFile.createContiguous(sd.vwd(), - TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { - error("createContiguous failed"); + Serial.println(&name[BASE_NAME_SIZE+2]); + if (!sd.exists(name)) { + Serial.println(F("File does not exist")); + return; } - // Get the address of the file on the SD. - if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { - error("contiguousRange failed"); + binFile.close(); + strcpy(binName, name); + if (!binFile.open(binName, O_READ)) { + Serial.println(F("open failed")); + return; } + Serial.println(F("File opened")); +} +//------------------------------------------------------------------------------ +void recordBinFile() { + const uint8_t QUEUE_DIM = BUFFER_BLOCK_COUNT + 1; + // Index of last queue location. + const uint8_t QUEUE_LAST = QUEUE_DIM - 1; + + // Allocate extra buffer space. + block_t block[BUFFER_BLOCK_COUNT - 1]; + + block_t* curBlock = 0; + + block_t* emptyStack[BUFFER_BLOCK_COUNT]; + uint8_t emptyTop; + uint8_t minTop; + + block_t* fullQueue[QUEUE_DIM]; + uint8_t fullHead = 0; + uint8_t fullTail = 0; + // Use SdFat's internal buffer. - uint8_t* cache = (uint8_t*)sd.vol()->cacheClear(); - if (cache == 0) { + emptyStack[0] = (block_t*)sd.vol()->cacheClear(); + if (emptyStack[0] == 0) { error("cacheClear failed"); } - - // Flash erase all data in the file. - Serial.println(F("Erasing all data")); - uint32_t bgnErase = bgnBlock; - uint32_t endErase; - while (bgnErase < endBlock) { - endErase = bgnErase + ERASE_SIZE; - if (endErase > endBlock) { - endErase = endBlock; - } - if (!sd.card()->erase(bgnErase, endErase)) { - error("erase failed"); - } - bgnErase = endErase + 1; + // Put rest of buffers on the empty stack. + for (int i = 1; i < BUFFER_BLOCK_COUNT; i++) { + emptyStack[i] = &block[i - 1]; } + emptyTop = BUFFER_BLOCK_COUNT; + minTop = BUFFER_BLOCK_COUNT; + // Start a multiple block write. - if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) { - error("writeBegin failed"); - } - // Initialize queues. - emptyHead = emptyTail = 0; - fullHead = fullTail = 0; - - // Use SdFat buffer for one block. - emptyQueue[emptyHead] = (block_t*)cache; - emptyHead = queueNext(emptyHead); - - // Put rest of buffers in the empty queue. - for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) { - emptyQueue[emptyHead] = &block[i]; - emptyHead = queueNext(emptyHead); + if (!sd.card()->writeStart(binFile.firstBlock())) { + error("writeStart failed"); } + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); Serial.println(F("Logging - type any character to stop")); - // 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 bn = 0; + uint32_t maxLatency = 0; uint32_t overrun = 0; uint32_t overrunTotal = 0; - uint32_t count = 0; - uint32_t maxDelta = 0; - uint32_t minDelta = 99999; - uint32_t maxLatency = 0; uint32_t logTime = micros(); - - // Set time for first record of file. - startMicros = logTime + LOG_INTERVAL_USEC; - - while (1) { - // Time for next data record. + while(1) { + // Time for next data record. logTime += LOG_INTERVAL_USEC; if (Serial.available()) { closeFile = true; - } - + } if (closeFile) { if (curBlock != 0) { // Put buffer in full queue. fullQueue[fullHead] = curBlock; - fullHead = queueNext(fullHead); + fullHead = fullHead < QUEUE_LAST ? fullHead + 1 : 0; curBlock = 0; } } else { - if (curBlock == 0 && emptyTail != emptyHead) { - curBlock = emptyQueue[emptyTail]; - emptyTail = queueNext(emptyTail); + if (curBlock == 0 && emptyTop != 0) { + curBlock = emptyStack[--emptyTop]; + if (emptyTop < minTop) { + minTop = emptyTop; + } curBlock->count = 0; curBlock->overrun = overrun; overrun = 0; @@ -435,24 +420,29 @@ void logData() { } while (delta < 0); if (curBlock == 0) { overrun++; + overrunTotal++; + if (ERROR_LED_PIN >= 0) { + digitalWrite(ERROR_LED_PIN, HIGH); + } +#if ABORT_ON_OVERRUN + Serial.println(F("Overrun abort")); + break; + #endif // ABORT_ON_OVERRUN } else { - if (useSharedSpi) { - sd.card()->chipSelectHigh(); - } +#if USE_SHARED_SPI + sd.card()->spiStop(); +#endif // USE_SHARED_SPI acquireData(&curBlock->data[curBlock->count++]); - if (useSharedSpi) { - sd.card()->chipSelectLow(); - } +#if USE_SHARED_SPI + sd.card()->spiStart(); +#endif // USE_SHARED_SPI if (curBlock->count == DATA_DIM) { fullQueue[fullHead] = curBlock; - fullHead = queueNext(fullHead); + fullHead = fullHead < QUEUE_LAST ? fullHead + 1 : 0; curBlock = 0; - } - if ((uint32_t)delta > maxDelta) maxDelta = delta; - if ((uint32_t)delta < minDelta) minDelta = delta; + } } } - if (fullHead == fullTail) { // Exit loop if done. if (closeFile) { @@ -461,29 +451,18 @@ void logData() { } else if (!sd.card()->isBusy()) { // Get address of block to write. block_t* pBlock = fullQueue[fullTail]; - fullTail = queueNext(fullTail); + fullTail = fullTail < QUEUE_LAST ? fullTail + 1 : 0; // Write block to SD. uint32_t usec = micros(); if (!sd.card()->writeData((uint8_t*)pBlock)) { error("write data failed"); } usec = micros() - usec; - t1 = millis(); if (usec > maxLatency) { maxLatency = usec; } - count += pBlock->count; - - // Add overruns and possibly light LED. - if (pBlock->overrun) { - overrunTotal += pBlock->overrun; - if (ERROR_LED_PIN >= 0) { - digitalWrite(ERROR_LED_PIN, HIGH); - } - } // Move block to empty queue. - emptyQueue[emptyHead] = pBlock; - emptyHead = queueNext(emptyHead); + emptyStack[emptyTop++] = pBlock; bn++; if (bn == FILE_BLOCK_COUNT) { // File full so stop @@ -494,6 +473,12 @@ void logData() { if (!sd.card()->writeStop()) { error("writeStop failed"); } + Serial.print(F("Min Free buffers: ")); + Serial.println(minTop); + Serial.print(F("Max block write usec: ")); + Serial.println(maxLatency); + Serial.print(F("Overruns: ")); + Serial.println(overrunTotal); // Truncate file if recording stopped early. if (bn != FILE_BLOCK_COUNT) { Serial.println(F("Truncating file")); @@ -501,25 +486,76 @@ void logData() { error("Can't truncate file"); } } +} +//------------------------------------------------------------------------------ +void recoverTmpFile() { + uint16_t count; + if (!binFile.open(TMP_FILE_NAME, O_RDWR)) { + return; + } + if (binFile.read(&count, 2) != 2 || count != DATA_DIM) { + error("Please delete existing " TMP_FILE_NAME); + } + Serial.println(F("\nRecovering data in tmp file " TMP_FILE_NAME)); + uint32_t bgnBlock = 0; + uint32_t endBlock = binFile.fileSize()/512 - 1; + // find last used block. + while (bgnBlock < endBlock) { + uint32_t midBlock = (bgnBlock + endBlock + 1)/2; + binFile.seekSet(512*midBlock); + if (binFile.read(&count, 2) != 2) error("read"); + if (count == 0 || count > DATA_DIM) { + endBlock = midBlock - 1; + } else { + bgnBlock = midBlock; + } + } + // truncate after last used block. + if (!binFile.truncate(512*(bgnBlock + 1))) { + error("Truncate " TMP_FILE_NAME " failed"); + } + renameBinFile(); +} +//----------------------------------------------------------------------------- +void renameBinFile() { + while (sd.exists(binName)) { + if (binName[BASE_NAME_SIZE + 1] != '9') { + binName[BASE_NAME_SIZE + 1]++; + } else { + binName[BASE_NAME_SIZE + 1] = '0'; + if (binName[BASE_NAME_SIZE] == '9') { + error("Can't create file name"); + } + binName[BASE_NAME_SIZE]++; + } + } if (!binFile.rename(sd.vwd(), binName)) { error("Can't rename file"); - } + } Serial.print(F("File renamed: ")); Serial.println(binName); - Serial.print(F("Max block write usec: ")); - 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: ")); - Serial.println((1000.0)*count/(t1-t0)); - Serial.print(F("Overruns: ")); - Serial.println(overrunTotal); - Serial.println(F("Done")); + Serial.print(F("File size: ")); + Serial.print(binFile.fileSize()/512); + Serial.println(F(" blocks")); +} +//------------------------------------------------------------------------------ +void testSensor() { + const uint32_t interval = 200000; + int32_t diff; + data_t data; + Serial.println(F("\nTesting - type any character to stop\n")); + // Wait for Serial Idle. + delay(1000); + printHeader(&Serial); + uint32_t m = micros(); + while (!Serial.available()) { + m += interval; + do { + diff = m - micros(); + } while (diff > 0); + acquireData(&data); + printData(&Serial, &data); + } } //------------------------------------------------------------------------------ void setup(void) { @@ -532,19 +568,38 @@ void setup(void) { while (!Serial) { SysCall::yield(); } - - Serial.print(F("FreeStack: ")); + Serial.print(F("\nFreeStack: ")); Serial.println(FreeStack()); Serial.print(F("Records/block: ")); Serial.println(DATA_DIM); if (sizeof(block_t) != 512) { error("Invalid block size"); } - // initialize file system. - if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) { - sd.initErrorPrint(); + // Allow userSetup access to SPI bus. + pinMode(SD_CS_PIN, OUTPUT); + digitalWrite(SD_CS_PIN, HIGH); + + // Setup sensors. + userSetup(); + + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) { + sd.initErrorPrint(&Serial); fatalBlink(); } + // recover existing tmp file. + if (sd.exists(TMP_FILE_NAME)) { + Serial.println(F("\nType 'Y' to recover existing tmp file " TMP_FILE_NAME)); + while (!Serial.available()) { + SysCall::yield(); + } + if (Serial.read() == 'Y') { + recoverTmpFile(); + } else { + error("'Y' not typed, please manually delete " TMP_FILE_NAME); + } + } } //------------------------------------------------------------------------------ void loop(void) { @@ -554,14 +609,21 @@ void loop(void) { } while (Serial.available() && Serial.read() >= 0); Serial.println(); Serial.println(F("type:")); + Serial.println(F("b - open existing bin file")); Serial.println(F("c - convert file to csv")); Serial.println(F("d - dump data to Serial")); Serial.println(F("e - overrun error details")); + Serial.println(F("l - list files")); Serial.println(F("r - record data")); - + Serial.println(F("t - test without logging")); while(!Serial.available()) { SysCall::yield(); } +#if WDT_YIELD_TIME_MICROS + Serial.println(F("LowLatencyLogger can not run with watchdog timer")); + SysCall::halt(); +#endif + char c = tolower(Serial.read()); // Discard extra Serial data. @@ -572,15 +634,22 @@ void loop(void) { if (ERROR_LED_PIN >= 0) { digitalWrite(ERROR_LED_PIN, LOW); } - if (c == 'c') { + if (c == 'b') { + openBinFile(); + } else if (c == 'c') { binaryToCsv(); } else if (c == 'd') { dumpData(); } else if (c == 'e') { checkOverrun(); + } else if (c == 'l') { + Serial.println(F("\nls:")); + sd.ls(&Serial, LS_SIZE); } else if (c == 'r') { logData(); + } else if (c == 't') { + testSensor(); } else { Serial.println(F("Invalid entry")); } -} +} \ No newline at end of file diff --git a/examples/LowLatencyLogger/UserFunctions.cpp b/examples/LowLatencyLogger/UserFunctions.cpp new file mode 100644 index 00000000..559b11c0 --- /dev/null +++ b/examples/LowLatencyLogger/UserFunctions.cpp @@ -0,0 +1,41 @@ +#include "UserTypes.h" +// User data functions. Modify these functions for your data items. + +// Start time for data +static uint32_t startMicros; + +// Acquire a data record. +void acquireData(data_t* data) { + data->time = micros(); + for (int i = 0; i < ADC_DIM; i++) { + data->adc[i] = analogRead(i); + } +} + +// Print a data record. +void printData(Print* pr, data_t* data) { + if (startMicros == 0) { + startMicros = data->time; + } + pr->print(data->time - startMicros); + for (int i = 0; i < ADC_DIM; i++) { + pr->write(','); + pr->print(data->adc[i]); + } + pr->println(); +} + +// Print data header. +void printHeader(Print* pr) { + startMicros = 0; + pr->print(F("micros")); + for (int i = 0; i < ADC_DIM; i++) { + pr->print(F(",adc")); + pr->print(i); + } + pr->println(); +} + +// Sensor setup +void userSetup() { +} diff --git a/examples/LowLatencyLogger/UserTypes.h b/examples/LowLatencyLogger/UserTypes.h new file mode 100644 index 00000000..7ccae8fa --- /dev/null +++ b/examples/LowLatencyLogger/UserTypes.h @@ -0,0 +1,15 @@ +#ifndef UserTypes_h +#define UserTypes_h +#include "Arduino.h" +// User data types. Modify for your data items. +#define FILE_BASE_NAME "adc4pin" +const uint8_t ADC_DIM = 4; +struct data_t { + uint32_t time; + uint16_t adc[ADC_DIM]; +}; +void acquireData(data_t* data); +void printData(Print* pr, data_t* data); +void printHeader(Print* pr); +void userSetup(); +#endif // UserTypes_h diff --git a/examples/LowLatencyLoggerADXL345/LowLatencyLogger.ino b/examples/LowLatencyLoggerADXL345/LowLatencyLogger.ino new file mode 100644 index 00000000..35cd3821 --- /dev/null +++ b/examples/LowLatencyLoggerADXL345/LowLatencyLogger.ino @@ -0,0 +1,655 @@ +/** + * This program logs data to a binary file. Functions are included + * to convert the binary file to a csv text file. + * + * Samples are logged at regular intervals. The maximum logging rate + * depends on the quality of your SD card and the time required to + * read sensor data. This example has been tested at 500 Hz with + * good SD card on an Uno. 4000 HZ is possible on a Due. + * + * If your SD card has a long write latency, it may be necessary to use + * slower sample rates. Using a Mega Arduino helps overcome latency + * problems since 12 512 byte buffers will be used. + * + * Data is written to the file using a SD multiple block write command. + */ +#include +#include "SdFat.h" +#include "FreeStack.h" +#include "UserTypes.h" + +#ifdef __AVR_ATmega328P__ +#include "MinimumSerial.h" +MinimumSerial MinSerial; +#define Serial MinSerial +#endif // __AVR_ATmega328P__ +//============================================================================== +// Start of configuration constants. +//============================================================================== +// Abort run on an overrun. Data before the overrun will be saved. +#define ABORT_ON_OVERRUN 1 +//------------------------------------------------------------------------------ +//Interval between data records in microseconds. +const uint32_t LOG_INTERVAL_USEC = 2000; +//------------------------------------------------------------------------------ +// Set USE_SHARED_SPI non-zero for use of an SPI sensor. +// May not work for some cards. +#ifndef USE_SHARED_SPI +#define USE_SHARED_SPI 0 +#endif // USE_SHARED_SPI +//------------------------------------------------------------------------------ +// Pin definitions. +// +// SD chip select pin. +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 +// overrun errors and logging continues unless ABORT_ON_OVERRUN +// is non-zero. +#ifdef ERROR_LED_PIN +#undef ERROR_LED_PIN +#endif // ERROR_LED_PIN +const int8_t ERROR_LED_PIN = -1; +//------------------------------------------------------------------------------ +// File definitions. +// +// Maximum file size in blocks. +// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks. +// This file is flash erased using special SD commands. The file will be +// truncated if logging is stopped early. +const uint32_t FILE_BLOCK_COUNT = 256000; +// +// log file base name if not defined in UserTypes.h +#ifndef FILE_BASE_NAME +#define FILE_BASE_NAME "data" +#endif // FILE_BASE_NAME +//------------------------------------------------------------------------------ +// Buffer definitions. +// +// The logger will use SdFat's buffer plus BUFFER_BLOCK_COUNT-1 additional +// buffers. +// +#ifndef RAMEND +// Assume ARM. Use total of ten 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 10; +// +#elif RAMEND < 0X8FF +#error Too little SRAM +// +#elif RAMEND < 0X10FF +// Use total of two 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 2; +// +#elif RAMEND < 0X20FF +// Use total of four 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 4; +// +#else // RAMEND +// Use total of 12 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 12; +#endif // RAMEND +//============================================================================== +// End of configuration constants. +//============================================================================== +// Temporary log file. Will be deleted if a reset or power failure occurs. +#define TMP_FILE_NAME FILE_BASE_NAME "##.bin" + +// Size of file base name. +const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1; +const uint8_t FILE_NAME_DIM = BASE_NAME_SIZE + 7; +char binName[FILE_NAME_DIM] = FILE_BASE_NAME "00.bin"; + +SdFat sd; + +SdBaseFile binFile; + +// Number of data records in a block. +const uint16_t DATA_DIM = (512 - 4)/sizeof(data_t); + +//Compute fill so block size is 512 bytes. FILL_DIM may be zero. +const uint16_t FILL_DIM = 512 - 4 - DATA_DIM*sizeof(data_t); + +struct block_t { + uint16_t count; + uint16_t overrun; + data_t data[DATA_DIM]; + uint8_t fill[FILL_DIM]; +}; +//============================================================================== +// Error messages stored in flash. +#define error(msg) {sd.errorPrint(&Serial, F(msg));fatalBlink();} +//------------------------------------------------------------------------------ +// +void fatalBlink() { + while (true) { + SysCall::yield(); + if (ERROR_LED_PIN >= 0) { + digitalWrite(ERROR_LED_PIN, HIGH); + delay(200); + digitalWrite(ERROR_LED_PIN, LOW); + delay(200); + } + } +} +//------------------------------------------------------------------------------ +// read data file and check for overruns +void checkOverrun() { + bool headerPrinted = false; + block_t block; + uint32_t bn = 0; + + if (!binFile.isOpen()) { + Serial.println(); + Serial.println(F("No current binary file")); + return; + } + binFile.rewind(); + Serial.println(); + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + Serial.println(F("Checking overrun errors - type any character to stop")); + while (binFile.read(&block, 512) == 512) { + if (block.count == 0) { + break; + } + if (block.overrun) { + if (!headerPrinted) { + Serial.println(); + Serial.println(F("Overruns:")); + Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount")); + headerPrinted = true; + } + Serial.print(bn); + Serial.print(','); + Serial.print(binFile.firstBlock() + bn); + Serial.print(','); + Serial.println(block.overrun); + } + bn++; + } + if (!headerPrinted) { + Serial.println(F("No errors found")); + } else { + Serial.println(F("Done")); + } +} +//----------------------------------------------------------------------------- +// Convert binary file to csv file. +void binaryToCsv() { + uint8_t lastPct = 0; + block_t block; + uint32_t t0 = millis(); + uint32_t syncCluster = 0; + SdFile csvFile; + char csvName[FILE_NAME_DIM]; + + if (!binFile.isOpen()) { + Serial.println(); + Serial.println(F("No current binary file")); + return; + } + Serial.println(); + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + + // Create a new csvFile. + strcpy(csvName, binName); + strcpy(&csvName[BASE_NAME_SIZE + 3], "csv"); + + if (!csvFile.open(csvName, O_WRITE | O_CREAT | O_TRUNC)) { + error("open csvFile failed"); + } + binFile.rewind(); + Serial.print(F("Writing: ")); + Serial.print(csvName); + Serial.println(F(" - type any character to stop")); + printHeader(&csvFile); + uint32_t tPct = millis(); + while (!Serial.available() && binFile.read(&block, 512) == 512) { + uint16_t i; + if (block.count == 0 || block.count > DATA_DIM) { + break; + } + if (block.overrun) { + csvFile.print(F("OVERRUN,")); + csvFile.println(block.overrun); + } + for (i = 0; i < block.count; i++) { + printData(&csvFile, &block.data[i]); + } + if (csvFile.curCluster() != syncCluster) { + csvFile.sync(); + syncCluster = csvFile.curCluster(); + } + if ((millis() - tPct) > 1000) { + uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100); + if (pct != lastPct) { + tPct = millis(); + lastPct = pct; + Serial.print(pct, DEC); + Serial.println('%'); + } + } + if (Serial.available()) { + break; + } + } + csvFile.close(); + Serial.print(F("Done: ")); + Serial.print(0.001*(millis() - t0)); + Serial.println(F(" Seconds")); +} +//----------------------------------------------------------------------------- +void createBinFile() { + // max number of blocks to erase per erase call + const uint32_t ERASE_SIZE = 262144L; + uint32_t bgnBlock, endBlock; + + // Delete old tmp file. + if (sd.exists(TMP_FILE_NAME)) { + Serial.println(F("Deleting tmp file " TMP_FILE_NAME)); + if (!sd.remove(TMP_FILE_NAME)) { + error("Can't remove tmp file"); + } + } + // Create new file. + Serial.println(F("\nCreating new file")); + binFile.close(); + if (!binFile.createContiguous(TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { + error("createContiguous failed"); + } + // Get the address of the file on the SD. + if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { + error("contiguousRange failed"); + } + // Flash erase all data in the file. + Serial.println(F("Erasing all data")); + uint32_t bgnErase = bgnBlock; + uint32_t endErase; + while (bgnErase < endBlock) { + endErase = bgnErase + ERASE_SIZE; + if (endErase > endBlock) { + endErase = endBlock; + } + if (!sd.card()->erase(bgnErase, endErase)) { + error("erase failed"); + } + bgnErase = endErase + 1; + } +} +//------------------------------------------------------------------------------ +// dump data file to Serial +void dumpData() { + block_t block; + if (!binFile.isOpen()) { + Serial.println(); + Serial.println(F("No current binary file")); + return; + } + binFile.rewind(); + Serial.println(); + Serial.println(F("Type any character to stop")); + delay(1000); + printHeader(&Serial); + while (!Serial.available() && binFile.read(&block , 512) == 512) { + if (block.count == 0) { + break; + } + if (block.overrun) { + Serial.print(F("OVERRUN,")); + Serial.println(block.overrun); + } + for (uint16_t i = 0; i < block.count; i++) { + printData(&Serial, &block.data[i]); + } + } + Serial.println(F("Done")); +} +//------------------------------------------------------------------------------ +// log data +void logData() { + createBinFile(); + recordBinFile(); + renameBinFile(); +} +//------------------------------------------------------------------------------ +void openBinFile() { + char name[FILE_NAME_DIM]; + strcpy(name, binName); + Serial.println(F("\nEnter two digit version")); + Serial.write(name, BASE_NAME_SIZE); + for (int i = 0; i < 2; i++) { + while (!Serial.available()) { + SysCall::yield(); + } + char c = Serial.read(); + Serial.write(c); + if (c < '0' || c > '9') { + Serial.println(F("\nInvalid digit")); + return; + } + name[BASE_NAME_SIZE + i] = c; + } + Serial.println(&name[BASE_NAME_SIZE+2]); + if (!sd.exists(name)) { + Serial.println(F("File does not exist")); + return; + } + binFile.close(); + strcpy(binName, name); + if (!binFile.open(binName, O_READ)) { + Serial.println(F("open failed")); + return; + } + Serial.println(F("File opened")); +} +//------------------------------------------------------------------------------ +void recordBinFile() { + const uint8_t QUEUE_DIM = BUFFER_BLOCK_COUNT + 1; + // Index of last queue location. + const uint8_t QUEUE_LAST = QUEUE_DIM - 1; + + // Allocate extra buffer space. + block_t block[BUFFER_BLOCK_COUNT - 1]; + + block_t* curBlock = 0; + + block_t* emptyStack[BUFFER_BLOCK_COUNT]; + uint8_t emptyTop; + uint8_t minTop; + + block_t* fullQueue[QUEUE_DIM]; + uint8_t fullHead = 0; + uint8_t fullTail = 0; + + // Use SdFat's internal buffer. + emptyStack[0] = (block_t*)sd.vol()->cacheClear(); + if (emptyStack[0] == 0) { + error("cacheClear failed"); + } + // Put rest of buffers on the empty stack. + for (int i = 1; i < BUFFER_BLOCK_COUNT; i++) { + emptyStack[i] = &block[i - 1]; + } + emptyTop = BUFFER_BLOCK_COUNT; + minTop = BUFFER_BLOCK_COUNT; + + // Start a multiple block write. + if (!sd.card()->writeStart(binFile.firstBlock())) { + error("writeStart failed"); + } + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + Serial.println(F("Logging - type any character to stop")); + bool closeFile = false; + uint32_t bn = 0; + uint32_t maxLatency = 0; + uint32_t overrun = 0; + uint32_t overrunTotal = 0; + uint32_t logTime = micros(); + while(1) { + // Time for next data record. + logTime += LOG_INTERVAL_USEC; + if (Serial.available()) { + closeFile = true; + } + if (closeFile) { + if (curBlock != 0) { + // Put buffer in full queue. + fullQueue[fullHead] = curBlock; + fullHead = fullHead < QUEUE_LAST ? fullHead + 1 : 0; + curBlock = 0; + } + } else { + if (curBlock == 0 && emptyTop != 0) { + curBlock = emptyStack[--emptyTop]; + if (emptyTop < minTop) { + minTop = emptyTop; + } + curBlock->count = 0; + curBlock->overrun = overrun; + overrun = 0; + } + if ((int32_t)(logTime - micros()) < 0) { + error("Rate too fast"); + } + int32_t delta; + do { + delta = micros() - logTime; + } while (delta < 0); + if (curBlock == 0) { + overrun++; + overrunTotal++; + if (ERROR_LED_PIN >= 0) { + digitalWrite(ERROR_LED_PIN, HIGH); + } +#if ABORT_ON_OVERRUN + Serial.println(F("Overrun abort")); + break; + #endif // ABORT_ON_OVERRUN + } else { +#if USE_SHARED_SPI + sd.card()->spiStop(); +#endif // USE_SHARED_SPI + acquireData(&curBlock->data[curBlock->count++]); +#if USE_SHARED_SPI + sd.card()->spiStart(); +#endif // USE_SHARED_SPI + if (curBlock->count == DATA_DIM) { + fullQueue[fullHead] = curBlock; + fullHead = fullHead < QUEUE_LAST ? fullHead + 1 : 0; + curBlock = 0; + } + } + } + if (fullHead == fullTail) { + // Exit loop if done. + if (closeFile) { + break; + } + } else if (!sd.card()->isBusy()) { + // Get address of block to write. + block_t* pBlock = fullQueue[fullTail]; + fullTail = fullTail < QUEUE_LAST ? fullTail + 1 : 0; + // Write block to SD. + uint32_t usec = micros(); + if (!sd.card()->writeData((uint8_t*)pBlock)) { + error("write data failed"); + } + usec = micros() - usec; + if (usec > maxLatency) { + maxLatency = usec; + } + // Move block to empty queue. + emptyStack[emptyTop++] = pBlock; + bn++; + if (bn == FILE_BLOCK_COUNT) { + // File full so stop + break; + } + } + } + if (!sd.card()->writeStop()) { + error("writeStop failed"); + } + Serial.print(F("Min Free buffers: ")); + Serial.println(minTop); + Serial.print(F("Max block write usec: ")); + Serial.println(maxLatency); + Serial.print(F("Overruns: ")); + Serial.println(overrunTotal); + // Truncate file if recording stopped early. + if (bn != FILE_BLOCK_COUNT) { + Serial.println(F("Truncating file")); + if (!binFile.truncate(512L * bn)) { + error("Can't truncate file"); + } + } +} +//------------------------------------------------------------------------------ +void recoverTmpFile() { + uint16_t count; + if (!binFile.open(TMP_FILE_NAME, O_RDWR)) { + return; + } + if (binFile.read(&count, 2) != 2 || count != DATA_DIM) { + error("Please delete existing " TMP_FILE_NAME); + } + Serial.println(F("\nRecovering data in tmp file " TMP_FILE_NAME)); + uint32_t bgnBlock = 0; + uint32_t endBlock = binFile.fileSize()/512 - 1; + // find last used block. + while (bgnBlock < endBlock) { + uint32_t midBlock = (bgnBlock + endBlock + 1)/2; + binFile.seekSet(512*midBlock); + if (binFile.read(&count, 2) != 2) error("read"); + if (count == 0 || count > DATA_DIM) { + endBlock = midBlock - 1; + } else { + bgnBlock = midBlock; + } + } + // truncate after last used block. + if (!binFile.truncate(512*(bgnBlock + 1))) { + error("Truncate " TMP_FILE_NAME " failed"); + } + renameBinFile(); +} +//----------------------------------------------------------------------------- +void renameBinFile() { + while (sd.exists(binName)) { + if (binName[BASE_NAME_SIZE + 1] != '9') { + binName[BASE_NAME_SIZE + 1]++; + } else { + binName[BASE_NAME_SIZE + 1] = '0'; + if (binName[BASE_NAME_SIZE] == '9') { + error("Can't create file name"); + } + binName[BASE_NAME_SIZE]++; + } + } + if (!binFile.rename(sd.vwd(), binName)) { + error("Can't rename file"); + } + Serial.print(F("File renamed: ")); + Serial.println(binName); + Serial.print(F("File size: ")); + Serial.print(binFile.fileSize()/512); + Serial.println(F(" blocks")); +} +//------------------------------------------------------------------------------ +void testSensor() { + const uint32_t interval = 200000; + int32_t diff; + data_t data; + Serial.println(F("\nTesting - type any character to stop\n")); + // Wait for Serial Idle. + delay(1000); + printHeader(&Serial); + uint32_t m = micros(); + while (!Serial.available()) { + m += interval; + do { + diff = m - micros(); + } while (diff > 0); + acquireData(&data); + printData(&Serial, &data); + } +} +//------------------------------------------------------------------------------ +void setup(void) { + if (ERROR_LED_PIN >= 0) { + pinMode(ERROR_LED_PIN, OUTPUT); + } + Serial.begin(9600); + + // Wait for USB Serial + while (!Serial) { + SysCall::yield(); + } + Serial.print(F("\nFreeStack: ")); + Serial.println(FreeStack()); + Serial.print(F("Records/block: ")); + Serial.println(DATA_DIM); + if (sizeof(block_t) != 512) { + error("Invalid block size"); + } + // Allow userSetup access to SPI bus. + pinMode(SD_CS_PIN, OUTPUT); + digitalWrite(SD_CS_PIN, HIGH); + + // Setup sensors. + userSetup(); + + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) { + sd.initErrorPrint(&Serial); + fatalBlink(); + } + // recover existing tmp file. + if (sd.exists(TMP_FILE_NAME)) { + Serial.println(F("\nType 'Y' to recover existing tmp file " TMP_FILE_NAME)); + while (!Serial.available()) { + SysCall::yield(); + } + if (Serial.read() == 'Y') { + recoverTmpFile(); + } else { + error("'Y' not typed, please manually delete " TMP_FILE_NAME); + } + } +} +//------------------------------------------------------------------------------ +void loop(void) { + // Read any Serial data. + do { + delay(10); + } while (Serial.available() && Serial.read() >= 0); + Serial.println(); + Serial.println(F("type:")); + Serial.println(F("b - open existing bin file")); + Serial.println(F("c - convert file to csv")); + Serial.println(F("d - dump data to Serial")); + Serial.println(F("e - overrun error details")); + Serial.println(F("l - list files")); + Serial.println(F("r - record data")); + Serial.println(F("t - test without logging")); + while(!Serial.available()) { + SysCall::yield(); + } +#if WDT_YIELD_TIME_MICROS + Serial.println(F("LowLatencyLogger can not run with watchdog timer")); + SysCall::halt(); +#endif + + char c = tolower(Serial.read()); + + // Discard extra Serial data. + do { + delay(10); + } while (Serial.available() && Serial.read() >= 0); + + if (ERROR_LED_PIN >= 0) { + digitalWrite(ERROR_LED_PIN, LOW); + } + if (c == 'b') { + openBinFile(); + } else if (c == 'c') { + binaryToCsv(); + } else if (c == 'd') { + dumpData(); + } else if (c == 'e') { + checkOverrun(); + } else if (c == 'l') { + Serial.println(F("\nls:")); + sd.ls(&Serial, LS_SIZE); + } else if (c == 'r') { + logData(); + } else if (c == 't') { + testSensor(); + } else { + Serial.println(F("Invalid entry")); + } +} \ No newline at end of file diff --git a/examples/LowLatencyLoggerADXL345/LowLatencyLoggerADXL345.ino b/examples/LowLatencyLoggerADXL345/LowLatencyLoggerADXL345.ino new file mode 100644 index 00000000..91c8fcc5 --- /dev/null +++ b/examples/LowLatencyLoggerADXL345/LowLatencyLoggerADXL345.ino @@ -0,0 +1 @@ +// Empty file with name LowLatencyLoggerADXL345.ino to make IDE happy. \ No newline at end of file diff --git a/examples/LowLatencyLoggerADXL345/UserFunctions.cpp b/examples/LowLatencyLoggerADXL345/UserFunctions.cpp new file mode 100644 index 00000000..71d624f6 --- /dev/null +++ b/examples/LowLatencyLoggerADXL345/UserFunctions.cpp @@ -0,0 +1,70 @@ +#include "UserTypes.h" +// User data functions. Modify these functions for your data items. + +// Start time for data +static uint32_t startMicros; + +const uint8_t ADXL345_CS = 9; + +const uint8_t POWER_CTL = 0x2D; //Power Control Register +const uint8_t DATA_FORMAT = 0x31; +const uint8_t DATAX0 = 0x32; //X-Axis Data 0 +const uint8_t DATAX1 = 0x33; //X-Axis Data 1 +const uint8_t DATAY0 = 0x34; //Y-Axis Data 0 +const uint8_t DATAY1 = 0x35; //Y-Axis Data 1 +const uint8_t DATAZ0 = 0x36; //Z-Axis Data 0 +const uint8_t DATAZ1 = 0x37; //Z-Axis Data 1 + +void writeADXL345Register(const uint8_t registerAddress, const uint8_t value) { + // Max SPI clock frequency is 5 MHz with CPOL = 1 and CPHA = 1. + SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3)); + digitalWrite(ADXL345_CS, LOW); + SPI.transfer(registerAddress); + SPI.transfer(value); + digitalWrite(ADXL345_CS, HIGH); + SPI.endTransaction(); +} + +void userSetup() { + SPI.begin(); + pinMode(ADXL345_CS, OUTPUT); + digitalWrite(ADXL345_CS, HIGH); + //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register. + writeADXL345Register(DATA_FORMAT, 0x01); + //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register. + writeADXL345Register(POWER_CTL, 0x08); //Measurement mode +} + +// Acquire a data record. +void acquireData(data_t* data) { + // Max SPI clock frequency is 5 MHz with CPOL = 1 and CPHA = 1. + SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3)); + data->time = micros(); + digitalWrite(ADXL345_CS, LOW); + // Read multiple bytes so or 0XC0 with address. + SPI.transfer(DATAX0 | 0XC0); + data->accel[0] = SPI.transfer(0) | (SPI.transfer(0) << 8); + data->accel[1] = SPI.transfer(0) | (SPI.transfer(0) << 8); + data->accel[2] = SPI.transfer(0) | (SPI.transfer(0) << 8); + digitalWrite(ADXL345_CS, HIGH); + SPI.endTransaction(); +} + +// Print a data record. +void printData(Print* pr, data_t* data) { + if (startMicros == 0) { + startMicros = data->time; + } + pr->print(data->time - startMicros); + for (int i = 0; i < ACCEL_DIM; i++) { + pr->write(','); + pr->print(data->accel[i]); + } + pr->println(); +} + +// Print data header. +void printHeader(Print* pr) { + startMicros = 0; + pr->println(F("micros,ax,ay,az")); +} diff --git a/examples/LowLatencyLoggerADXL345/UserTypes.h b/examples/LowLatencyLoggerADXL345/UserTypes.h new file mode 100644 index 00000000..56bc8738 --- /dev/null +++ b/examples/LowLatencyLoggerADXL345/UserTypes.h @@ -0,0 +1,17 @@ +#ifndef UserTypes_h +#define UserTypes_h +#include "Arduino.h" +#include "SPI.h" +#define USE_SHARED_SPI 1 +#define FILE_BASE_NAME "ADXL4G" +// User data types. Modify for your data items. +const uint8_t ACCEL_DIM = 3; +struct data_t { + uint32_t time; + int16_t accel[ACCEL_DIM]; +}; +void acquireData(data_t* data); +void printData(Print* pr, data_t* data); +void printHeader(Print* pr); +void userSetup(); +#endif // UserTypes_h diff --git a/examples/LowLatencyLoggerADXL345/readme.txt b/examples/LowLatencyLoggerADXL345/readme.txt new file mode 100644 index 00000000..a68ba787 --- /dev/null +++ b/examples/LowLatencyLoggerADXL345/readme.txt @@ -0,0 +1 @@ +Test of shared SPI for LowLatencyLogger. \ No newline at end of file diff --git a/examples/LowLatencyLoggerMPU6050/LowLatencyLogger.ino b/examples/LowLatencyLoggerMPU6050/LowLatencyLogger.ino new file mode 100644 index 00000000..35cd3821 --- /dev/null +++ b/examples/LowLatencyLoggerMPU6050/LowLatencyLogger.ino @@ -0,0 +1,655 @@ +/** + * This program logs data to a binary file. Functions are included + * to convert the binary file to a csv text file. + * + * Samples are logged at regular intervals. The maximum logging rate + * depends on the quality of your SD card and the time required to + * read sensor data. This example has been tested at 500 Hz with + * good SD card on an Uno. 4000 HZ is possible on a Due. + * + * If your SD card has a long write latency, it may be necessary to use + * slower sample rates. Using a Mega Arduino helps overcome latency + * problems since 12 512 byte buffers will be used. + * + * Data is written to the file using a SD multiple block write command. + */ +#include +#include "SdFat.h" +#include "FreeStack.h" +#include "UserTypes.h" + +#ifdef __AVR_ATmega328P__ +#include "MinimumSerial.h" +MinimumSerial MinSerial; +#define Serial MinSerial +#endif // __AVR_ATmega328P__ +//============================================================================== +// Start of configuration constants. +//============================================================================== +// Abort run on an overrun. Data before the overrun will be saved. +#define ABORT_ON_OVERRUN 1 +//------------------------------------------------------------------------------ +//Interval between data records in microseconds. +const uint32_t LOG_INTERVAL_USEC = 2000; +//------------------------------------------------------------------------------ +// Set USE_SHARED_SPI non-zero for use of an SPI sensor. +// May not work for some cards. +#ifndef USE_SHARED_SPI +#define USE_SHARED_SPI 0 +#endif // USE_SHARED_SPI +//------------------------------------------------------------------------------ +// Pin definitions. +// +// SD chip select pin. +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 +// overrun errors and logging continues unless ABORT_ON_OVERRUN +// is non-zero. +#ifdef ERROR_LED_PIN +#undef ERROR_LED_PIN +#endif // ERROR_LED_PIN +const int8_t ERROR_LED_PIN = -1; +//------------------------------------------------------------------------------ +// File definitions. +// +// Maximum file size in blocks. +// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks. +// This file is flash erased using special SD commands. The file will be +// truncated if logging is stopped early. +const uint32_t FILE_BLOCK_COUNT = 256000; +// +// log file base name if not defined in UserTypes.h +#ifndef FILE_BASE_NAME +#define FILE_BASE_NAME "data" +#endif // FILE_BASE_NAME +//------------------------------------------------------------------------------ +// Buffer definitions. +// +// The logger will use SdFat's buffer plus BUFFER_BLOCK_COUNT-1 additional +// buffers. +// +#ifndef RAMEND +// Assume ARM. Use total of ten 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 10; +// +#elif RAMEND < 0X8FF +#error Too little SRAM +// +#elif RAMEND < 0X10FF +// Use total of two 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 2; +// +#elif RAMEND < 0X20FF +// Use total of four 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 4; +// +#else // RAMEND +// Use total of 12 512 byte buffers. +const uint8_t BUFFER_BLOCK_COUNT = 12; +#endif // RAMEND +//============================================================================== +// End of configuration constants. +//============================================================================== +// Temporary log file. Will be deleted if a reset or power failure occurs. +#define TMP_FILE_NAME FILE_BASE_NAME "##.bin" + +// Size of file base name. +const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1; +const uint8_t FILE_NAME_DIM = BASE_NAME_SIZE + 7; +char binName[FILE_NAME_DIM] = FILE_BASE_NAME "00.bin"; + +SdFat sd; + +SdBaseFile binFile; + +// Number of data records in a block. +const uint16_t DATA_DIM = (512 - 4)/sizeof(data_t); + +//Compute fill so block size is 512 bytes. FILL_DIM may be zero. +const uint16_t FILL_DIM = 512 - 4 - DATA_DIM*sizeof(data_t); + +struct block_t { + uint16_t count; + uint16_t overrun; + data_t data[DATA_DIM]; + uint8_t fill[FILL_DIM]; +}; +//============================================================================== +// Error messages stored in flash. +#define error(msg) {sd.errorPrint(&Serial, F(msg));fatalBlink();} +//------------------------------------------------------------------------------ +// +void fatalBlink() { + while (true) { + SysCall::yield(); + if (ERROR_LED_PIN >= 0) { + digitalWrite(ERROR_LED_PIN, HIGH); + delay(200); + digitalWrite(ERROR_LED_PIN, LOW); + delay(200); + } + } +} +//------------------------------------------------------------------------------ +// read data file and check for overruns +void checkOverrun() { + bool headerPrinted = false; + block_t block; + uint32_t bn = 0; + + if (!binFile.isOpen()) { + Serial.println(); + Serial.println(F("No current binary file")); + return; + } + binFile.rewind(); + Serial.println(); + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + Serial.println(F("Checking overrun errors - type any character to stop")); + while (binFile.read(&block, 512) == 512) { + if (block.count == 0) { + break; + } + if (block.overrun) { + if (!headerPrinted) { + Serial.println(); + Serial.println(F("Overruns:")); + Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount")); + headerPrinted = true; + } + Serial.print(bn); + Serial.print(','); + Serial.print(binFile.firstBlock() + bn); + Serial.print(','); + Serial.println(block.overrun); + } + bn++; + } + if (!headerPrinted) { + Serial.println(F("No errors found")); + } else { + Serial.println(F("Done")); + } +} +//----------------------------------------------------------------------------- +// Convert binary file to csv file. +void binaryToCsv() { + uint8_t lastPct = 0; + block_t block; + uint32_t t0 = millis(); + uint32_t syncCluster = 0; + SdFile csvFile; + char csvName[FILE_NAME_DIM]; + + if (!binFile.isOpen()) { + Serial.println(); + Serial.println(F("No current binary file")); + return; + } + Serial.println(); + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + + // Create a new csvFile. + strcpy(csvName, binName); + strcpy(&csvName[BASE_NAME_SIZE + 3], "csv"); + + if (!csvFile.open(csvName, O_WRITE | O_CREAT | O_TRUNC)) { + error("open csvFile failed"); + } + binFile.rewind(); + Serial.print(F("Writing: ")); + Serial.print(csvName); + Serial.println(F(" - type any character to stop")); + printHeader(&csvFile); + uint32_t tPct = millis(); + while (!Serial.available() && binFile.read(&block, 512) == 512) { + uint16_t i; + if (block.count == 0 || block.count > DATA_DIM) { + break; + } + if (block.overrun) { + csvFile.print(F("OVERRUN,")); + csvFile.println(block.overrun); + } + for (i = 0; i < block.count; i++) { + printData(&csvFile, &block.data[i]); + } + if (csvFile.curCluster() != syncCluster) { + csvFile.sync(); + syncCluster = csvFile.curCluster(); + } + if ((millis() - tPct) > 1000) { + uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100); + if (pct != lastPct) { + tPct = millis(); + lastPct = pct; + Serial.print(pct, DEC); + Serial.println('%'); + } + } + if (Serial.available()) { + break; + } + } + csvFile.close(); + Serial.print(F("Done: ")); + Serial.print(0.001*(millis() - t0)); + Serial.println(F(" Seconds")); +} +//----------------------------------------------------------------------------- +void createBinFile() { + // max number of blocks to erase per erase call + const uint32_t ERASE_SIZE = 262144L; + uint32_t bgnBlock, endBlock; + + // Delete old tmp file. + if (sd.exists(TMP_FILE_NAME)) { + Serial.println(F("Deleting tmp file " TMP_FILE_NAME)); + if (!sd.remove(TMP_FILE_NAME)) { + error("Can't remove tmp file"); + } + } + // Create new file. + Serial.println(F("\nCreating new file")); + binFile.close(); + if (!binFile.createContiguous(TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { + error("createContiguous failed"); + } + // Get the address of the file on the SD. + if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { + error("contiguousRange failed"); + } + // Flash erase all data in the file. + Serial.println(F("Erasing all data")); + uint32_t bgnErase = bgnBlock; + uint32_t endErase; + while (bgnErase < endBlock) { + endErase = bgnErase + ERASE_SIZE; + if (endErase > endBlock) { + endErase = endBlock; + } + if (!sd.card()->erase(bgnErase, endErase)) { + error("erase failed"); + } + bgnErase = endErase + 1; + } +} +//------------------------------------------------------------------------------ +// dump data file to Serial +void dumpData() { + block_t block; + if (!binFile.isOpen()) { + Serial.println(); + Serial.println(F("No current binary file")); + return; + } + binFile.rewind(); + Serial.println(); + Serial.println(F("Type any character to stop")); + delay(1000); + printHeader(&Serial); + while (!Serial.available() && binFile.read(&block , 512) == 512) { + if (block.count == 0) { + break; + } + if (block.overrun) { + Serial.print(F("OVERRUN,")); + Serial.println(block.overrun); + } + for (uint16_t i = 0; i < block.count; i++) { + printData(&Serial, &block.data[i]); + } + } + Serial.println(F("Done")); +} +//------------------------------------------------------------------------------ +// log data +void logData() { + createBinFile(); + recordBinFile(); + renameBinFile(); +} +//------------------------------------------------------------------------------ +void openBinFile() { + char name[FILE_NAME_DIM]; + strcpy(name, binName); + Serial.println(F("\nEnter two digit version")); + Serial.write(name, BASE_NAME_SIZE); + for (int i = 0; i < 2; i++) { + while (!Serial.available()) { + SysCall::yield(); + } + char c = Serial.read(); + Serial.write(c); + if (c < '0' || c > '9') { + Serial.println(F("\nInvalid digit")); + return; + } + name[BASE_NAME_SIZE + i] = c; + } + Serial.println(&name[BASE_NAME_SIZE+2]); + if (!sd.exists(name)) { + Serial.println(F("File does not exist")); + return; + } + binFile.close(); + strcpy(binName, name); + if (!binFile.open(binName, O_READ)) { + Serial.println(F("open failed")); + return; + } + Serial.println(F("File opened")); +} +//------------------------------------------------------------------------------ +void recordBinFile() { + const uint8_t QUEUE_DIM = BUFFER_BLOCK_COUNT + 1; + // Index of last queue location. + const uint8_t QUEUE_LAST = QUEUE_DIM - 1; + + // Allocate extra buffer space. + block_t block[BUFFER_BLOCK_COUNT - 1]; + + block_t* curBlock = 0; + + block_t* emptyStack[BUFFER_BLOCK_COUNT]; + uint8_t emptyTop; + uint8_t minTop; + + block_t* fullQueue[QUEUE_DIM]; + uint8_t fullHead = 0; + uint8_t fullTail = 0; + + // Use SdFat's internal buffer. + emptyStack[0] = (block_t*)sd.vol()->cacheClear(); + if (emptyStack[0] == 0) { + error("cacheClear failed"); + } + // Put rest of buffers on the empty stack. + for (int i = 1; i < BUFFER_BLOCK_COUNT; i++) { + emptyStack[i] = &block[i - 1]; + } + emptyTop = BUFFER_BLOCK_COUNT; + minTop = BUFFER_BLOCK_COUNT; + + // Start a multiple block write. + if (!sd.card()->writeStart(binFile.firstBlock())) { + error("writeStart failed"); + } + Serial.print(F("FreeStack: ")); + Serial.println(FreeStack()); + Serial.println(F("Logging - type any character to stop")); + bool closeFile = false; + uint32_t bn = 0; + uint32_t maxLatency = 0; + uint32_t overrun = 0; + uint32_t overrunTotal = 0; + uint32_t logTime = micros(); + while(1) { + // Time for next data record. + logTime += LOG_INTERVAL_USEC; + if (Serial.available()) { + closeFile = true; + } + if (closeFile) { + if (curBlock != 0) { + // Put buffer in full queue. + fullQueue[fullHead] = curBlock; + fullHead = fullHead < QUEUE_LAST ? fullHead + 1 : 0; + curBlock = 0; + } + } else { + if (curBlock == 0 && emptyTop != 0) { + curBlock = emptyStack[--emptyTop]; + if (emptyTop < minTop) { + minTop = emptyTop; + } + curBlock->count = 0; + curBlock->overrun = overrun; + overrun = 0; + } + if ((int32_t)(logTime - micros()) < 0) { + error("Rate too fast"); + } + int32_t delta; + do { + delta = micros() - logTime; + } while (delta < 0); + if (curBlock == 0) { + overrun++; + overrunTotal++; + if (ERROR_LED_PIN >= 0) { + digitalWrite(ERROR_LED_PIN, HIGH); + } +#if ABORT_ON_OVERRUN + Serial.println(F("Overrun abort")); + break; + #endif // ABORT_ON_OVERRUN + } else { +#if USE_SHARED_SPI + sd.card()->spiStop(); +#endif // USE_SHARED_SPI + acquireData(&curBlock->data[curBlock->count++]); +#if USE_SHARED_SPI + sd.card()->spiStart(); +#endif // USE_SHARED_SPI + if (curBlock->count == DATA_DIM) { + fullQueue[fullHead] = curBlock; + fullHead = fullHead < QUEUE_LAST ? fullHead + 1 : 0; + curBlock = 0; + } + } + } + if (fullHead == fullTail) { + // Exit loop if done. + if (closeFile) { + break; + } + } else if (!sd.card()->isBusy()) { + // Get address of block to write. + block_t* pBlock = fullQueue[fullTail]; + fullTail = fullTail < QUEUE_LAST ? fullTail + 1 : 0; + // Write block to SD. + uint32_t usec = micros(); + if (!sd.card()->writeData((uint8_t*)pBlock)) { + error("write data failed"); + } + usec = micros() - usec; + if (usec > maxLatency) { + maxLatency = usec; + } + // Move block to empty queue. + emptyStack[emptyTop++] = pBlock; + bn++; + if (bn == FILE_BLOCK_COUNT) { + // File full so stop + break; + } + } + } + if (!sd.card()->writeStop()) { + error("writeStop failed"); + } + Serial.print(F("Min Free buffers: ")); + Serial.println(minTop); + Serial.print(F("Max block write usec: ")); + Serial.println(maxLatency); + Serial.print(F("Overruns: ")); + Serial.println(overrunTotal); + // Truncate file if recording stopped early. + if (bn != FILE_BLOCK_COUNT) { + Serial.println(F("Truncating file")); + if (!binFile.truncate(512L * bn)) { + error("Can't truncate file"); + } + } +} +//------------------------------------------------------------------------------ +void recoverTmpFile() { + uint16_t count; + if (!binFile.open(TMP_FILE_NAME, O_RDWR)) { + return; + } + if (binFile.read(&count, 2) != 2 || count != DATA_DIM) { + error("Please delete existing " TMP_FILE_NAME); + } + Serial.println(F("\nRecovering data in tmp file " TMP_FILE_NAME)); + uint32_t bgnBlock = 0; + uint32_t endBlock = binFile.fileSize()/512 - 1; + // find last used block. + while (bgnBlock < endBlock) { + uint32_t midBlock = (bgnBlock + endBlock + 1)/2; + binFile.seekSet(512*midBlock); + if (binFile.read(&count, 2) != 2) error("read"); + if (count == 0 || count > DATA_DIM) { + endBlock = midBlock - 1; + } else { + bgnBlock = midBlock; + } + } + // truncate after last used block. + if (!binFile.truncate(512*(bgnBlock + 1))) { + error("Truncate " TMP_FILE_NAME " failed"); + } + renameBinFile(); +} +//----------------------------------------------------------------------------- +void renameBinFile() { + while (sd.exists(binName)) { + if (binName[BASE_NAME_SIZE + 1] != '9') { + binName[BASE_NAME_SIZE + 1]++; + } else { + binName[BASE_NAME_SIZE + 1] = '0'; + if (binName[BASE_NAME_SIZE] == '9') { + error("Can't create file name"); + } + binName[BASE_NAME_SIZE]++; + } + } + if (!binFile.rename(sd.vwd(), binName)) { + error("Can't rename file"); + } + Serial.print(F("File renamed: ")); + Serial.println(binName); + Serial.print(F("File size: ")); + Serial.print(binFile.fileSize()/512); + Serial.println(F(" blocks")); +} +//------------------------------------------------------------------------------ +void testSensor() { + const uint32_t interval = 200000; + int32_t diff; + data_t data; + Serial.println(F("\nTesting - type any character to stop\n")); + // Wait for Serial Idle. + delay(1000); + printHeader(&Serial); + uint32_t m = micros(); + while (!Serial.available()) { + m += interval; + do { + diff = m - micros(); + } while (diff > 0); + acquireData(&data); + printData(&Serial, &data); + } +} +//------------------------------------------------------------------------------ +void setup(void) { + if (ERROR_LED_PIN >= 0) { + pinMode(ERROR_LED_PIN, OUTPUT); + } + Serial.begin(9600); + + // Wait for USB Serial + while (!Serial) { + SysCall::yield(); + } + Serial.print(F("\nFreeStack: ")); + Serial.println(FreeStack()); + Serial.print(F("Records/block: ")); + Serial.println(DATA_DIM); + if (sizeof(block_t) != 512) { + error("Invalid block size"); + } + // Allow userSetup access to SPI bus. + pinMode(SD_CS_PIN, OUTPUT); + digitalWrite(SD_CS_PIN, HIGH); + + // Setup sensors. + userSetup(); + + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) { + sd.initErrorPrint(&Serial); + fatalBlink(); + } + // recover existing tmp file. + if (sd.exists(TMP_FILE_NAME)) { + Serial.println(F("\nType 'Y' to recover existing tmp file " TMP_FILE_NAME)); + while (!Serial.available()) { + SysCall::yield(); + } + if (Serial.read() == 'Y') { + recoverTmpFile(); + } else { + error("'Y' not typed, please manually delete " TMP_FILE_NAME); + } + } +} +//------------------------------------------------------------------------------ +void loop(void) { + // Read any Serial data. + do { + delay(10); + } while (Serial.available() && Serial.read() >= 0); + Serial.println(); + Serial.println(F("type:")); + Serial.println(F("b - open existing bin file")); + Serial.println(F("c - convert file to csv")); + Serial.println(F("d - dump data to Serial")); + Serial.println(F("e - overrun error details")); + Serial.println(F("l - list files")); + Serial.println(F("r - record data")); + Serial.println(F("t - test without logging")); + while(!Serial.available()) { + SysCall::yield(); + } +#if WDT_YIELD_TIME_MICROS + Serial.println(F("LowLatencyLogger can not run with watchdog timer")); + SysCall::halt(); +#endif + + char c = tolower(Serial.read()); + + // Discard extra Serial data. + do { + delay(10); + } while (Serial.available() && Serial.read() >= 0); + + if (ERROR_LED_PIN >= 0) { + digitalWrite(ERROR_LED_PIN, LOW); + } + if (c == 'b') { + openBinFile(); + } else if (c == 'c') { + binaryToCsv(); + } else if (c == 'd') { + dumpData(); + } else if (c == 'e') { + checkOverrun(); + } else if (c == 'l') { + Serial.println(F("\nls:")); + sd.ls(&Serial, LS_SIZE); + } else if (c == 'r') { + logData(); + } else if (c == 't') { + testSensor(); + } else { + Serial.println(F("Invalid entry")); + } +} \ No newline at end of file diff --git a/examples/LowLatencyLoggerMPU6050/LowLatencyLoggerMPU6050.ino b/examples/LowLatencyLoggerMPU6050/LowLatencyLoggerMPU6050.ino new file mode 100644 index 00000000..53bfe066 --- /dev/null +++ b/examples/LowLatencyLoggerMPU6050/LowLatencyLoggerMPU6050.ino @@ -0,0 +1,2 @@ +// Empty file with name LowLatencyLoggerMPU6050.ino to make IDE happy. + diff --git a/examples/LowLatencyLoggerMPU6050/UserFunctions.cpp b/examples/LowLatencyLoggerMPU6050/UserFunctions.cpp new file mode 100644 index 00000000..606a40d6 --- /dev/null +++ b/examples/LowLatencyLoggerMPU6050/UserFunctions.cpp @@ -0,0 +1,51 @@ +// User data functions. Modify these functions for your data items. +#include "UserTypes.h" +#include "Wire.h" +#include "I2Cdev.h" +#include "MPU6050.h" +//------------------------------------------------------------------------------ +MPU6050 mpu; +static uint32_t startMicros; +// Acquire a data record. +void acquireData(data_t* data) { + data->time = micros(); + mpu.getMotion6(&data->ax, &data->ay, &data->az, + &data->gx, &data->gy, &data->gz); +} + +// setup AVR I2C +void userSetup() { +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + Wire.begin(); + Wire.setClock(400000); +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + Fastwire::setup(400, true); +#endif + mpu.initialize(); +} + +// Print a data record. +void printData(Print* pr, data_t* data) { + if (startMicros == 0) { + startMicros = data->time; + } + pr->print(data->time- startMicros); + pr->write(','); + pr->print(data->ax); + pr->write(','); + pr->print(data->ay); + pr->write(','); + pr->print(data->az); + pr->write(','); + pr->print(data->gx); + pr->write(','); + pr->print(data->gy); + pr->write(','); + pr->println(data->gz); +} + +// Print data header. +void printHeader(Print* pr) { + startMicros = 0; + pr->println(F("micros,ax,ay,az,gx,gy,gz")); +} diff --git a/examples/LowLatencyLoggerMPU6050/UserTypes.h b/examples/LowLatencyLoggerMPU6050/UserTypes.h new file mode 100644 index 00000000..73c2a423 --- /dev/null +++ b/examples/LowLatencyLoggerMPU6050/UserTypes.h @@ -0,0 +1,18 @@ +#ifndef UserTypes_h +#define UserTypes_h +#include "Arduino.h" +#define FILE_BASE_NAME "mpuraw" +struct data_t { + unsigned long time; + int16_t ax; + int16_t ay; + int16_t az; + int16_t gx; + int16_t gy; + int16_t gz; +}; +void acquireData(data_t* data); +void printData(Print* pr, data_t* data); +void printHeader(Print* pr); +void userSetup(); +#endif // UserTypes_h diff --git a/SdFat/examples/OpenNext/OpenNext.ino b/examples/OpenNext/OpenNext.ino similarity index 87% rename from SdFat/examples/OpenNext/OpenNext.ino rename to examples/OpenNext/OpenNext.ino index 80e3f72b..65dee761 100644 --- a/SdFat/examples/OpenNext/OpenNext.ino +++ b/examples/OpenNext/OpenNext.ino @@ -25,9 +25,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/PrintBenchmark/PrintBenchmark.ino b/examples/PrintBenchmark/PrintBenchmark.ino similarity index 95% rename from SdFat/examples/PrintBenchmark/PrintBenchmark.ino rename to examples/PrintBenchmark/PrintBenchmark.ino index a87ccdbe..4bd39dd2 100644 --- a/SdFat/examples/PrintBenchmark/PrintBenchmark.ino +++ b/examples/PrintBenchmark/PrintBenchmark.ino @@ -49,9 +49,9 @@ void loop() { cout << F("FreeStack: ") << FreeStack() << endl; - // initialize the SD card at SPI_FULL_SPEED for best performance. - // try SPI_HALF_SPEED if bus errors occur. - if (!sd.begin(chipSelect, SPI_FULL_SPEED)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/QuickStart/QuickStart.ino b/examples/QuickStart/QuickStart.ino similarity index 92% rename from SdFat/examples/QuickStart/QuickStart.ino rename to examples/QuickStart/QuickStart.ino index e6ac4b43..e295011b 100644 --- a/SdFat/examples/QuickStart/QuickStart.ino +++ b/examples/QuickStart/QuickStart.ino @@ -1,4 +1,4 @@ -// Quick hardware test. +// Quick hardware test for SPI card access. // #include #include "SdFat.h" @@ -8,10 +8,10 @@ // to 10 to disable the Ethernet controller. const int8_t DISABLE_CHIP_SELECT = -1; // -// Test with reduced SPI speed for breadboards. -// Change spiSpeed to SPI_FULL_SPEED for better performance -// Use SPI_QUARTER_SPEED for even slower SPI bus speed -const uint8_t spiSpeed = SPI_HALF_SPEED; +// Test with reduced SPI speed for breadboards. SD_SCK_MHZ(4) will select +// the highest speed supported by the board that is not over 4 MHz. +// Change SPI_SPEED to SD_SCK_MHZ(50) for best performance. +#define SPI_SPEED SD_SCK_MHZ(4) //------------------------------------------------------------------------------ // File system object. SdFat sd; @@ -28,7 +28,7 @@ int chipSelect; void cardOrSpeed() { cout << F("Try another SD card or reduce the SPI bus speed.\n"); - cout << F("Edit spiSpeed in this program to change it.\n"); + cout << F("Edit SPI_SPEED in this program to change it.\n"); } void reformatMsg() { @@ -98,7 +98,7 @@ void loop() { pinMode(DISABLE_CHIP_SELECT, OUTPUT); digitalWrite(DISABLE_CHIP_SELECT, HIGH); } - if (!sd.begin(chipSelect, spiSpeed)) { + if (!sd.begin(chipSelect, SPI_SPEED)) { if (sd.card()->errorCode()) { cout << F( "\nSD initialization failed.\n" diff --git a/SdFat/examples/RawWrite/RawWrite.ino b/examples/RawWrite/RawWrite.ino similarity index 95% rename from SdFat/examples/RawWrite/RawWrite.ino rename to examples/RawWrite/RawWrite.ino index c62651a7..97ff9a56 100644 --- a/SdFat/examples/RawWrite/RawWrite.ino +++ b/examples/RawWrite/RawWrite.ino @@ -64,9 +64,9 @@ void loop(void) { cout << F("FreeStack: ") << FreeStack() << endl; - // initialize the SD card at SPI_FULL_SPEED for best performance. - // try SPI_HALF_SPEED if bus errors occur. - if (!sd.begin(chipSelect, SPI_FULL_SPEED)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } @@ -74,7 +74,7 @@ void loop(void) { sd.remove("RawWrite.txt"); // create a contiguous file - if (!file.createContiguous(sd.vwd(), "RawWrite.txt", 512UL*BLOCK_COUNT)) { + if (!file.createContiguous("RawWrite.txt", 512UL*BLOCK_COUNT)) { error("createContiguous failed"); } // get the location of the file's blocks diff --git a/SdFat/examples/readCSV/readCSV.ino b/examples/ReadCsv/ReadCsv.ino similarity index 100% rename from SdFat/examples/readCSV/readCSV.ino rename to examples/ReadCsv/ReadCsv.ino diff --git a/SdFat/examples/ReadCsvArray/ReadCsvArray.ino b/examples/ReadCsvArray/ReadCsvArray.ino similarity index 100% rename from SdFat/examples/ReadCsvArray/ReadCsvArray.ino rename to examples/ReadCsvArray/ReadCsvArray.ino diff --git a/SdFat/examples/ReadCsvStream/ReadCsvStream.ino b/examples/ReadCsvStream/ReadCsvStream.ino similarity index 93% rename from SdFat/examples/ReadCsvStream/ReadCsvStream.ino rename to examples/ReadCsvStream/ReadCsvStream.ino index cd6e6fa7..a07611e6 100644 --- a/SdFat/examples/ReadCsvStream/ReadCsvStream.ino +++ b/examples/ReadCsvStream/ReadCsvStream.ino @@ -101,9 +101,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/ReadWrite/ReadWrite.ino b/examples/ReadWrite/ReadWrite.ino similarity index 81% rename from SdFat/examples/ReadWrite/ReadWrite.ino rename to examples/ReadWrite/ReadWrite.ino index 6e312ded..15b6c98c 100644 --- a/SdFat/examples/ReadWrite/ReadWrite.ino +++ b/examples/ReadWrite/ReadWrite.ino @@ -7,7 +7,6 @@ ** MOSI - pin 11 ** MISO - pin 12 ** CLK - pin 13 - ** CS - pin 4 created Nov 2010 by David A. Mellis @@ -17,30 +16,24 @@ This example code is in the public domain. */ -#define SD_CS_PIN SS + #include //#include #include "SdFat.h" SdFat SD; +#define SD_CS_PIN SS File myFile; -void setup() -{ +void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); - - // Wait for USB Serial while (!Serial) { - SysCall::yield(); + ; // wait for serial port to connect. Needed for native USB port only } + 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 - // (10 on most Arduino boards, 53 on the Mega) must be left as an output - // or the SD library functions will not work. - pinMode(10, OUTPUT); if (!SD.begin(SD_CS_PIN)) { Serial.println("initialization failed!"); @@ -81,8 +74,7 @@ void setup() } } -void loop() -{ +void loop() { // nothing happens after setup } diff --git a/examples/STM32Test/STM32Test.ino b/examples/STM32Test/STM32Test.ino new file mode 100644 index 00000000..5da3165f --- /dev/null +++ b/examples/STM32Test/STM32Test.ino @@ -0,0 +1,176 @@ +/* + * Example use of two SPI ports on an STM32 board. + * Note SPI speed is limited to 18 MHz. + */ +#include +#include "SdFat.h" +#include "FreeStack.h" + +// set ENABLE_EXTENDED_TRANSFER_CLASS non-zero to use faster EX classes + +// Use first SPI port +SdFat sd1(1); +// SdFatEX sd1(1); +const uint8_t SD1_CS = PA4; // chip select for sd1 + +// Use second SPI port +SdFat sd2(2); +// SdFatEX sd2(2); +const uint8_t SD2_CS = PB12; // chip select for sd2 + +const uint8_t BUF_DIM = 100; +uint8_t buf[BUF_DIM]; + +const uint32_t FILE_SIZE = 1000000; +const uint16_t NWRITE = FILE_SIZE/BUF_DIM; +//------------------------------------------------------------------------------ +// print error msg, any SD error codes, and halt. +// store messages in flash +#define errorExit(msg) errorHalt(F(msg)) +#define initError(msg) initErrorHalt(F(msg)) +//------------------------------------------------------------------------------ +void setup() { + Serial.begin(9600); + // Wait for USB Serial + while (!Serial) { + SysCall::yield(); + } + Serial.print(F("FreeStack: ")); + + Serial.println(FreeStack()); + + // fill buffer with known data + for (size_t i = 0; i < sizeof(buf); i++) { + buf[i] = i; + } + + Serial.println(F("type any character to start")); + while (!Serial.available()) { + SysCall::yield(); + } + + // initialize the first card + if (!sd1.begin(SD1_CS, SD_SCK_MHZ(18))) { + sd1.initError("sd1:"); + } + // create Dir1 on sd1 if it does not exist + if (!sd1.exists("/Dir1")) { + if (!sd1.mkdir("/Dir1")) { + sd1.errorExit("sd1.mkdir"); + } + } + // initialize the second card + if (!sd2.begin(SD2_CS, SD_SCK_MHZ(18))) { + sd2.initError("sd2:"); + } +// create Dir2 on sd2 if it does not exist + if (!sd2.exists("/Dir2")) { + if (!sd2.mkdir("/Dir2")) { + sd2.errorExit("sd2.mkdir"); + } + } + // list root directory on both cards + Serial.println(F("------sd1 root-------")); + sd1.ls(); + Serial.println(F("------sd2 root-------")); + sd2.ls(); + + // make /Dir1 the default directory for sd1 + if (!sd1.chdir("/Dir1")) { + sd1.errorExit("sd1.chdir"); + } + // remove test.bin from /Dir1 directory of sd1 + if (sd1.exists("test.bin")) { + if (!sd1.remove("test.bin")) { + sd2.errorExit("remove test.bin"); + } + } + // make /Dir2 the default directory for sd2 + if (!sd2.chdir("/Dir2")) { + sd2.errorExit("sd2.chdir"); + } + // remove rename.bin from /Dir2 directory of sd2 + if (sd2.exists("rename.bin")) { + if (!sd2.remove("rename.bin")) { + sd2.errorExit("remove rename.bin"); + } + } + // list current directory on both cards + Serial.println(F("------sd1 Dir1-------")); + sd1.ls(); + Serial.println(F("------sd2 Dir2-------")); + sd2.ls(); + Serial.println(F("---------------------")); + + // set the current working directory for open() to sd1 + sd1.chvol(); + + // create or open /Dir1/test.bin and truncate it to zero length + SdFile file1; + if (!file1.open("test.bin", O_RDWR | O_CREAT | O_TRUNC)) { + sd1.errorExit("file1"); + } + Serial.println(F("Writing test.bin to sd1")); + + // write data to /Dir1/test.bin on sd1 + for (uint16_t i = 0; i < NWRITE; i++) { + if (file1.write(buf, sizeof(buf)) != sizeof(buf)) { + sd1.errorExit("sd1.write"); + } + } + // set the current working directory for open() to sd2 + sd2.chvol(); + + // create or open /Dir2/copy.bin and truncate it to zero length + SdFile file2; + if (!file2.open("copy.bin", O_WRITE | O_CREAT | O_TRUNC)) { + sd2.errorExit("file2"); + } + Serial.println(F("Copying test.bin to copy.bin")); + + // copy file1 to file2 + file1.rewind(); + uint32_t t = millis(); + + while (1) { + int n = file1.read(buf, sizeof(buf)); + if (n < 0) { + sd1.errorExit("read1"); + } + if (n == 0) { + break; + } + if ((int)file2.write(buf, n) != n) { + sd2.errorExit("write2"); + } + } + t = millis() - t; + Serial.print(F("File size: ")); + Serial.println(file2.fileSize()); + Serial.print(F("Copy time: ")); + Serial.print(t); + Serial.println(F(" millis")); + // close test.bin + file1.close(); + file2.close(); + // list current directory on both cards + Serial.println(F("------sd1 -------")); + sd1.ls("/", LS_R | LS_DATE | LS_SIZE); + Serial.println(F("------sd2 -------")); + sd2.ls("/", LS_R | LS_DATE | LS_SIZE); + Serial.println(F("---------------------")); + Serial.println(F("Renaming copy.bin")); + // rename the copy + if (!sd2.rename("copy.bin", "rename.bin")) { + sd2.errorExit("sd2.rename"); + } + // list current directory on both cards + Serial.println(F("------sd1 -------")); + sd1.ls("/", LS_R | LS_DATE | LS_SIZE); + Serial.println(F("------sd2 -------")); + sd2.ls("/", LS_R | LS_DATE | LS_SIZE); + Serial.println(F("---------------------")); + Serial.println(F("Done")); +} +//------------------------------------------------------------------------------ +void loop() {} diff --git a/SdFat/examples/SdFormatter/SdFormatter.ino b/examples/SdFormatter/SdFormatter.ino similarity index 94% rename from SdFat/examples/SdFormatter/SdFormatter.ino rename to examples/SdFormatter/SdFormatter.ino index 123a7039..a0b9ba69 100644 --- a/SdFat/examples/SdFormatter/SdFormatter.ino +++ b/examples/SdFormatter/SdFormatter.ino @@ -11,13 +11,9 @@ * For smaller cards this program uses FAT16 * and SDFormatter uses FAT12. */ -// Print extra info for debug if DEBUG_PRINT is nonzero -#define DEBUG_PRINT 0 -#include -#include "SdFat.h" -#if DEBUG_PRINT -#include "FreeStack.h" -#endif // DEBUG_PRINT + +// Set USE_SDIO to zero for SPI card access. +#define USE_SDIO 0 // // Change the value of chipSelect if your hardware does // not use the default value, SS. Common values are: @@ -26,16 +22,31 @@ // Adafruit SD shields and modules: pin 10 const uint8_t chipSelect = SS; -// Change spiSpeed to SPI_FULL_SPEED for better performance -// Use SPI_QUARTER_SPEED for even slower SPI bus speed -const uint8_t spiSpeed = SPI_HALF_SPEED; +// Initialize at highest supported speed not over 50 MHz. +// Reduce max speed if errors occur. +#define SPI_SPEED SD_SCK_MHZ(50) + +// Print extra info for debug if DEBUG_PRINT is nonzero +#define DEBUG_PRINT 0 +#include +#include "SdFat.h" +#if DEBUG_PRINT +#include "FreeStack.h" +#endif // DEBUG_PRINT // Serial output stream ArduinoOutStream cout(Serial); +#if USE_SDIO +// Use faster SdioCardEX +SdioCardEX card; +// SdioCard card; +#else // USE_SDIO Sd2Card card; +#endif // USE_SDIO + uint32_t cardSizeBlocks; -uint16_t cardCapacityMB; +uint32_t cardCapacityMB; // cache for SD block cache_t cache; @@ -65,11 +76,9 @@ char noName[] = "NO NAME "; char fat16str[] = "FAT16 "; char fat32str[] = "FAT32 "; //------------------------------------------------------------------------------ -#define sdError(msg) sdError_F(F(msg)) - -void sdError_F(const __FlashStringHelper* str) { - cout << F("error: "); - cout << str << endl; +#define sdError(msg) {cout << F("error: ") << F(msg) << endl; sdErrorHalt();} +//------------------------------------------------------------------------------ +void sdErrorHalt() { if (card.errorCode()) { cout << F("SD error: ") << hex << int(card.errorCode()); cout << ',' << int(card.errorData()) << dec << endl; @@ -157,6 +166,16 @@ void clearCache(uint8_t addSig) { // zero FAT and root dir area on SD void clearFatDir(uint32_t bgn, uint32_t count) { clearCache(false); +#if USE_SDIO + for (uint32_t i = 0; i < count; i++) { + if (!card.writeBlock(bgn + i, cache.data)) { + sdError("Clear FAT/DIR writeBlock failed"); + } + if ((i & 0XFF) == 0) { + cout << '.'; + } + } +#else // USE_SDIO if (!card.writeStart(bgn, count)) { sdError("Clear FAT/DIR writeStart failed"); } @@ -171,6 +190,7 @@ void clearFatDir(uint32_t bgn, uint32_t count) { if (!card.writeStop()) { sdError("Clear FAT/DIR writeStop failed"); } +#endif // USE_SDIO cout << endl; } //------------------------------------------------------------------------------ @@ -498,14 +518,19 @@ void setup() { cout << F("Quiting, invalid option entered.") << endl; return; } - - if (!card.begin(chipSelect, spiSpeed)) { +#if USE_SDIO + if (!card.begin()) { + sdError("card.begin failed"); + } +#else // USE_SDIO + if (!card.begin(chipSelect, SPI_SPEED)) { cout << F( "\nSD initialization failure!\n" "Is the SD card inserted correctly?\n" "Is chip select correct at the top of this program?\n"); sdError("card.begin failed"); } +#endif cardSizeBlocks = card.cardSize(); if (cardSizeBlocks == 0) { sdError("cardSize"); diff --git a/SdFat/examples/SdInfo/SdInfo.ino b/examples/SdInfo/SdInfo.ino similarity index 89% rename from SdFat/examples/SdInfo/SdInfo.ino rename to examples/SdInfo/SdInfo.ino index c30fc89c..2b427581 100644 --- a/SdFat/examples/SdInfo/SdInfo.ino +++ b/examples/SdInfo/SdInfo.ino @@ -3,6 +3,9 @@ */ #include #include "SdFat.h" + +// Set USE_SDIO to zero for SPI card access. +#define USE_SDIO 0 /* * SD chip select pin. Common values are: * @@ -18,7 +21,14 @@ const uint8_t SD_CHIP_SELECT = SS; * to 10 to disable the Ethernet controller. */ const int8_t DISABLE_CHIP_SELECT = -1; + +#if USE_SDIO +// Use faster SdioCardEX +SdFatSdioEX sd; +// SdFatSdio sd; +#else // USE_SDIO SdFat sd; +#endif // USE_SDIO // serial output steam ArduinoOutStream cout(Serial); @@ -30,16 +40,7 @@ uint32_t cardSize; uint32_t eraseSize; //------------------------------------------------------------------------------ // store error strings in flash -#define sdErrorMsg(msg) sdErrorMsg_F(F(msg)); -void sdErrorMsg_F(const __FlashStringHelper* str) { - cout << str << endl; - if (sd.card()->errorCode()) { - cout << F("SD errorCode: "); - cout << hex << int(sd.card()->errorCode()) << endl; - cout << F("SD errorData: "); - cout << int(sd.card()->errorData()) << dec << endl; - } -} +#define sdErrorMsg(msg) sd.errorPrint(F(msg)); //------------------------------------------------------------------------------ uint8_t cidDmp() { cid_t cid; @@ -97,17 +98,13 @@ uint8_t csdDmp() { //------------------------------------------------------------------------------ // print partition table uint8_t partDmp() { - cache_t *p = sd.vol()->cacheClear(); - if (!p) { - sdErrorMsg("cacheClear failed"); - return false; - } - if (!sd.card()->readBlock(0, p->data)) { + mbr_t mbr; + if (!sd.card()->readBlock(0, (uint8_t*)&mbr)) { sdErrorMsg("read MBR failed"); return false; } for (uint8_t ip = 1; ip < 5; ip++) { - part_t *pt = &p->mbr.part[ip - 1]; + part_t *pt = &mbr.part[ip - 1]; if ((pt->boot & 0X7F) != 0 || pt->firstSector > cardSize) { cout << F("\nNo MBR. Assuming Super Floppy format.\n"); return true; @@ -116,7 +113,7 @@ uint8_t partDmp() { cout << F("\nSD Partition Table\n"); cout << F("part,boot,type,start,length\n"); for (uint8_t ip = 1; ip < 5; ip++) { - part_t *pt = &p->mbr.part[ip - 1]; + part_t *pt = &mbr.part[ip - 1]; cout << int(ip) << ',' << hex << int(pt->boot) << ',' << int(pt->type); cout << dec << ',' << pt->firstSector <<',' << pt->totalSectors << endl; } @@ -156,6 +153,7 @@ void setup() { // F stores strings in flash to save RAM cout << F("SdFat version: ") << SD_FAT_VERSION << endl; +#if !USE_SDIO if (DISABLE_CHIP_SELECT < 0) { cout << F( "\nAssuming the SD is the only SPI device.\n" @@ -168,6 +166,7 @@ void setup() { } cout << F("\nAssuming the SD chip select pin is: ") <cardSize(); diff --git a/SdFat/examples/SoftwareSpi/SoftwareSpi.ino b/examples/SoftwareSpi/SoftwareSpi.ino similarity index 86% rename from SdFat/examples/SoftwareSpi/SoftwareSpi.ino rename to examples/SoftwareSpi/SoftwareSpi.ino index d9eddc85..5d5846ac 100644 --- a/SdFat/examples/SoftwareSpi/SoftwareSpi.ino +++ b/examples/SoftwareSpi/SoftwareSpi.ino @@ -5,7 +5,7 @@ // #include #include "SdFat.h" -#if SD_SPI_CONFIGURATION >= 3 // Must be set in SdFat/SdFatConfig.h +#if ENABLE_SOFTWARE_SPI_CLASS // Must be set in SdFat/SdFatConfig.h // // Pin numbers in templates must be constants. const uint8_t SOFT_MISO_PIN = 12; @@ -53,6 +53,6 @@ void setup() { } //------------------------------------------------------------------------------ void loop() {} -#else // SD_SPI_CONFIGURATION >= 3 -#error SD_SPI_CONFIGURATION must be set to 3 in SdFat/SdFatConfig.h -#endif //SD_SPI_CONFIGURATION >= 3 \ No newline at end of file +#else // ENABLE_SOFTWARE_SPI_CLASS +#error ENABLE_SOFTWARE_SPI_CLASS must be set non-zero in SdFat/SdFatConfig.h +#endif //ENABLE_SOFTWARE_SPI_CLASS \ No newline at end of file diff --git a/SdFat/examples/StdioBench/StdioBench.ino b/examples/StdioBench/StdioBench.ino similarity index 94% rename from SdFat/examples/StdioBench/StdioBench.ino rename to examples/StdioBench/StdioBench.ino index 528788de..d1461832 100644 --- a/SdFat/examples/StdioBench/StdioBench.ino +++ b/examples/StdioBench/StdioBench.ino @@ -39,7 +39,10 @@ void setup() { SysCall::yield(); } Serial.println(F("Starting test")); - if (!sd.begin(SD_CS_PIN)) { + + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) { sd.errorHalt(); } @@ -137,10 +140,11 @@ void setup() { case 3: for (uint16_t i = 0; i < 10000; i++) { + uint32_t n = i + 1000000000UL; #if PRINT_FIELD - stdioFile.printField(i + 1000000000UL, '\n'); + stdioFile.printField(n, '\n'); #else // PRINT_FIELD - stdioFile.println(i + 1000000000UL); + stdioFile.println(n); #endif // PRINT_FIELD } break; diff --git a/examples/TeensySdioDemo/TeensySdioDemo.ino b/examples/TeensySdioDemo/TeensySdioDemo.ino new file mode 100644 index 00000000..988a9214 --- /dev/null +++ b/examples/TeensySdioDemo/TeensySdioDemo.ino @@ -0,0 +1,169 @@ +// Simple performance test for Teensy 3.5/3.6 SDHC. +// Demonstrates yield() efficiency. + +// Warning SdFatSdio and SdFatSdioEX normally should +// not both be used in a program. +// Each has its own cache and member variables. + +#include "SdFat.h" + +// 32 KiB buffer. +const size_t BUF_DIM = 32768; + +// 8 MiB file. +const uint32_t FILE_SIZE = 256UL*BUF_DIM; + +SdFatSdio sd; + +SdFatSdioEX sdEx; + +File file; + +uint8_t buf[BUF_DIM]; + +// buffer as uint32_t +uint32_t* buf32 = (uint32_t*)buf; + +// Total usec in read/write calls. +uint32_t totalMicros = 0; +// Time in yield() function. +uint32_t yieldMicros = 0; +// Number of yield calls. +uint32_t yieldCalls = 0; +// Max busy time for single yield call. +uint32_t yieldMaxUsec = 0; +// Control access to the two versions of SdFat. +bool useEx = false; +//----------------------------------------------------------------------------- +bool sdBusy() { + return useEx ? sdEx.card()->isBusy() : sd.card()->isBusy(); +} +//----------------------------------------------------------------------------- +void errorHalt(const char* msg) { + if (useEx) { + sdEx.errorHalt(msg); + } else { + sd.errorHalt(msg); + } +} +//------------------------------------------------------------------------------ +uint32_t kHzSdClk() { + return useEx ? sdEx.card()->kHzSdClk() : sd.card()->kHzSdClk(); +} +//------------------------------------------------------------------------------ +// Replace "weak" system yield() function. +void yield() { + // Only count cardBusy time. + if (!sdBusy()) { + return; + } + uint32_t m = micros(); + yieldCalls++; + while (sdBusy()) { + // Do something here. + } + m = micros() - m; + if (m > yieldMaxUsec) { + yieldMaxUsec = m; + } + yieldMicros += m; +} +//----------------------------------------------------------------------------- +void runTest() { + // Zero Stats + totalMicros = 0; + yieldMicros = 0; + yieldCalls = 0; + yieldMaxUsec = 0; + if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT)) { + errorHalt("open failed"); + } + Serial.println("\nsize,write,read"); + Serial.println("bytes,KB/sec,KB/sec"); + for (size_t nb = 512; nb <= BUF_DIM; nb *= 2) { + file.truncate(0); + uint32_t nRdWr = FILE_SIZE/nb; + Serial.print(nb); + Serial.print(','); + uint32_t t = micros(); + for (uint32_t n = 0; n < nRdWr; n++) { + // Set start and end of buffer. + buf32[0] = n; + buf32[nb/4 - 1] = n; + if (nb != file.write(buf, nb)) { + errorHalt("write failed"); + } + } + t = micros() - t; + totalMicros += t; + Serial.print(1000.0*FILE_SIZE/t); + Serial.print(','); + file.rewind(); + t = micros(); + + for (uint32_t n = 0; n < nRdWr; n++) { + if ((int)nb != file.read(buf, nb)) { + errorHalt("read failed"); + } + // crude check of data. + if (buf32[0] != n || buf32[nb/4 - 1] != n) { + errorHalt("data check"); + } + } + t = micros() - t; + totalMicros += t; + Serial.println(1000.0*FILE_SIZE/t); + } + file.close(); + Serial.print("\ntotalMicros "); + Serial.println(totalMicros); + Serial.print("yieldMicros "); + Serial.println(yieldMicros); + Serial.print("yieldCalls "); + Serial.println(yieldCalls); + Serial.print("yieldMaxUsec "); + Serial.println(yieldMaxUsec); + Serial.print("kHzSdClk "); + Serial.println(kHzSdClk()); + Serial.println("Done"); +} +//----------------------------------------------------------------------------- +void setup() { + Serial.begin(9600); + while (!Serial) { + } + Serial.println("SdFatSdioEX uses extended multi-block transfers without DMA."); + Serial.println("SdFatSdio uses a traditional DMA SDIO implementation."); + Serial.println("Note the difference is speed and busy yield time.\n"); +} +//----------------------------------------------------------------------------- +void loop() { + do { + delay(10); + } while (Serial.available() && Serial.read()); + + Serial.println("Type '1' for SdFatSdioEX or '2' for SdFatSdio"); + while (!Serial.available()) { + } + char c = Serial.read(); + if (c != '1' && c != '2') { + Serial.println("Invalid input"); + return; + } + if (c =='1') { + useEx = true; + if (!sdEx.begin()) { + sd.initErrorHalt("SdFatSdioEX begin() failed"); + } + // make sdEx the current volume. + sdEx.chvol(); + } else { + useEx = false; + if (!sd.begin()) { + sd.initErrorHalt("SdFatSdio begin() failed"); + } + // make sd the current volume. + sd.chvol(); + } + runTest(); +} \ No newline at end of file diff --git a/SdFat/examples/Timestamp/Timestamp.ino b/examples/Timestamp/Timestamp.ino similarity index 95% rename from SdFat/examples/Timestamp/Timestamp.ino rename to examples/Timestamp/Timestamp.ino index 2cbae359..d0b09d02 100644 --- a/SdFat/examples/Timestamp/Timestamp.ino +++ b/examples/Timestamp/Timestamp.ino @@ -83,9 +83,9 @@ void setup(void) { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/TwoCards/TwoCards.ino b/examples/TwoCards/TwoCards.ino similarity index 98% rename from SdFat/examples/TwoCards/TwoCards.ino rename to examples/TwoCards/TwoCards.ino index 764600ee..d77292c6 100644 --- a/SdFat/examples/TwoCards/TwoCards.ino +++ b/examples/TwoCards/TwoCards.ino @@ -1,4 +1,5 @@ /* + * Warning This example requires extra RAM and may crash on Uno. * Example use of two SD cards. */ #include diff --git a/SdFat/examples/VolumeFreeSpace/VolumeFreeSpace.ino b/examples/VolumeFreeSpace/VolumeFreeSpace.ino similarity index 92% rename from SdFat/examples/VolumeFreeSpace/VolumeFreeSpace.ino rename to examples/VolumeFreeSpace/VolumeFreeSpace.ino index 96dd2175..229843c3 100644 --- a/SdFat/examples/VolumeFreeSpace/VolumeFreeSpace.ino +++ b/examples/VolumeFreeSpace/VolumeFreeSpace.ino @@ -49,9 +49,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } // Insure no TEST_FILE. diff --git a/SdFat/examples/bench/bench.ino b/examples/bench/bench.ino similarity index 89% rename from SdFat/examples/bench/bench.ino rename to examples/bench/bench.ino index 3817cc2b..74fc0831 100644 --- a/SdFat/examples/bench/bench.ino +++ b/examples/bench/bench.ino @@ -5,6 +5,9 @@ #include "SdFat.h" #include "FreeStack.h" +// Set USE_SDIO to zero for SPI card access. +#define USE_SDIO 0 + // SD chip select pin const uint8_t chipSelect = SS; @@ -28,9 +31,20 @@ const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB; uint8_t buf[BUF_SIZE]; // file system +#if USE_SDIO +// Traditional DMA version. +// SdFatSdio sd; +// Faster version. +SdFatSdioEX sd; +#else // USE_SDIO SdFat sd; -// Set SD_SPI_CONFIGURATION to three to test next two definitions. -// SdFatLibSpi sd; +#endif // USE_SDIO + +// Set ENABLE_EXTENDED_TRANSFER_CLASS to use extended SD I/O. +// Requires dedicated use of the SPI bus. +// SdFatEX sd; + +// Set ENABLE_SOFTWARE_SPI_CLASS to use software SPI. // Args are misoPin, mosiPin, sckPin. // SdFatSoftSpi<6, 7, 5> sd; @@ -98,12 +112,17 @@ void loop() { cout << F("FreeStack: ") << FreeStack() << endl; - // initialize the SD card at SPI_FULL_SPEED for best performance. - // try SPI_HALF_SPEED if bus errors occur. - if (!sd.begin(chipSelect, SPI_FULL_SPEED)) { +#if USE_SDIO + if (!sd.begin()) { sd.initErrorHalt(); } - +#else // USE_SDIO + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { + sd.initErrorHalt(); + } +#endif // USE_SDIO cout << F("Type is FAT") << int(sd.vol()->fatType()) << endl; cout << F("Card size: ") << sd.card()->cardSize()*512E-9; cout << F(" GB (GB = 1E9 bytes)") << endl; diff --git a/SdFat/examples/dataLogger/dataLogger.ino b/examples/dataLogger/dataLogger.ino similarity index 95% rename from SdFat/examples/dataLogger/dataLogger.ino rename to examples/dataLogger/dataLogger.ino index 5ee11046..390273db 100644 --- a/SdFat/examples/dataLogger/dataLogger.ino +++ b/examples/dataLogger/dataLogger.ino @@ -79,9 +79,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/fgets/fgets.ino b/examples/fgets/fgets.ino similarity index 91% rename from SdFat/examples/fgets/fgets.ino rename to examples/fgets/fgets.ino index 5fcb5bde..6d3eb9fe 100644 --- a/SdFat/examples/fgets/fgets.ino +++ b/examples/fgets/fgets.ino @@ -72,9 +72,9 @@ void setup(void) { } 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/formatting/formatting.ino b/examples/formatting/formatting.ino similarity index 100% rename from SdFat/examples/formatting/formatting.ino rename to examples/formatting/formatting.ino diff --git a/SdFat/examples/getline/getline.ino b/examples/getline/getline.ino similarity index 92% rename from SdFat/examples/getline/getline.ino rename to examples/getline/getline.ino index 5271a1cb..e441651f 100644 --- a/SdFat/examples/getline/getline.ino +++ b/examples/getline/getline.ino @@ -66,9 +66,9 @@ void setup(void) { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/rename/rename.ino b/examples/rename/rename.ino similarity index 93% rename from SdFat/examples/rename/rename.ino rename to examples/rename/rename.ino index 370fe8e3..81c5d0ce 100644 --- a/SdFat/examples/rename/rename.ino +++ b/examples/rename/rename.ino @@ -29,9 +29,9 @@ void setup() { 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)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } diff --git a/SdFat/examples/wipe/wipe.ino b/examples/wipe/wipe.ino similarity index 66% rename from SdFat/examples/wipe/wipe.ino rename to examples/wipe/wipe.ino index 7dd31374..6d1bc936 100644 --- a/SdFat/examples/wipe/wipe.ino +++ b/examples/wipe/wipe.ino @@ -20,7 +20,9 @@ void setup() { if (c != 'Y') { sd.errorHalt("Quitting, you did not type 'Y'."); } - if (!sd.begin(chipSelect)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } // Use wipe() for no dot progress indicator. @@ -28,7 +30,9 @@ void setup() { sd.errorHalt("Wipe failed."); } // Must reinitialize after wipe. - if (!sd.begin(chipSelect)) { + // Initialize at the highest speed supported by the board that is + // not over 50 MHz. Try a lower speed if SPI errors occur. + if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.errorHalt("Second init failed."); } Serial.println("Done"); diff --git a/AnalogBinLoggerExtras/ADC_ENOB.PNG b/extras/AnalogBinLoggerExtras/ADC_ENOB.PNG similarity index 100% rename from AnalogBinLoggerExtras/ADC_ENOB.PNG rename to extras/AnalogBinLoggerExtras/ADC_ENOB.PNG diff --git a/AnalogBinLoggerExtras/ADCdocs/ATmegaADCAccuracy.pdf b/extras/AnalogBinLoggerExtras/ADCdocs/ATmegaADCAccuracy.pdf similarity index 100% rename from AnalogBinLoggerExtras/ADCdocs/ATmegaADCAccuracy.pdf rename to extras/AnalogBinLoggerExtras/ADCdocs/ATmegaADCAccuracy.pdf diff --git a/AnalogBinLoggerExtras/ADCdocs/ExcelFFT.pdf b/extras/AnalogBinLoggerExtras/ADCdocs/ExcelFFT.pdf similarity index 100% rename from AnalogBinLoggerExtras/ADCdocs/ExcelFFT.pdf rename to extras/AnalogBinLoggerExtras/ADCdocs/ExcelFFT.pdf diff --git a/AnalogBinLoggerExtras/AdcErrorStudy.txt b/extras/AnalogBinLoggerExtras/AdcErrorStudy.txt similarity index 100% rename from AnalogBinLoggerExtras/AdcErrorStudy.txt rename to extras/AnalogBinLoggerExtras/AdcErrorStudy.txt diff --git a/AnalogBinLoggerExtras/DATA.png b/extras/AnalogBinLoggerExtras/DATA.png similarity index 100% rename from AnalogBinLoggerExtras/DATA.png rename to extras/AnalogBinLoggerExtras/DATA.png diff --git a/AnalogBinLoggerExtras/FFT.png b/extras/AnalogBinLoggerExtras/FFT.png similarity index 100% rename from AnalogBinLoggerExtras/FFT.png rename to extras/AnalogBinLoggerExtras/FFT.png diff --git a/AnalogBinLoggerExtras/RateTable.txt b/extras/AnalogBinLoggerExtras/RateTable.txt similarity index 100% rename from AnalogBinLoggerExtras/RateTable.txt rename to extras/AnalogBinLoggerExtras/RateTable.txt diff --git a/AnalogBinLoggerExtras/bintocsv/AnalogBinLogger.h b/extras/AnalogBinLoggerExtras/bintocsv/AnalogBinLogger.h similarity index 100% rename from AnalogBinLoggerExtras/bintocsv/AnalogBinLogger.h rename to extras/AnalogBinLoggerExtras/bintocsv/AnalogBinLogger.h diff --git a/AnalogBinLoggerExtras/bintocsv/bintocsv.cpp b/extras/AnalogBinLoggerExtras/bintocsv/bintocsv.cpp similarity index 100% rename from AnalogBinLoggerExtras/bintocsv/bintocsv.cpp rename to extras/AnalogBinLoggerExtras/bintocsv/bintocsv.cpp diff --git a/AnalogBinLoggerExtras/bintocsv/bintocsv.exe b/extras/AnalogBinLoggerExtras/bintocsv/bintocsv.exe similarity index 100% rename from AnalogBinLoggerExtras/bintocsv/bintocsv.exe rename to extras/AnalogBinLoggerExtras/bintocsv/bintocsv.exe diff --git a/AnalogBinLoggerExtras/readme.txt b/extras/AnalogBinLoggerExtras/readme.txt similarity index 100% rename from AnalogBinLoggerExtras/readme.txt rename to extras/AnalogBinLoggerExtras/readme.txt diff --git a/SdFat/MainPage/SdFatmainpage.h b/extras/MainPage/SdFatmainpage.h similarity index 91% rename from SdFat/MainPage/SdFatmainpage.h rename to extras/MainPage/SdFatmainpage.h index 41eb21e8..b3c7346f 100644 --- a/SdFat/MainPage/SdFatmainpage.h +++ b/extras/MainPage/SdFatmainpage.h @@ -34,15 +34,17 @@ nonzero in SdFatConfig.h. The %SdFat library supports Long %File Names or short 8.3 names. Edit the SdFatConfig.h file to select short or long file names. -The main classes in %SdFat are SdFat, SdFatSoftSpi, SdFatLibSpi, +The main classes in %SdFat are SdFat, SdFatEX, SdFatSoftSpi, SdFatSoftSpiEX, SdBaseFile, SdFile, File, StdioStream, \ref fstream, \ref ifstream, and \ref ofstream. -The SdFat, SdFatLibSpi, and SdFatSoftSpi classes maintain a FAT volume, -a current working directory, and simplifies initialization of other classes. -The SdFat class uses a fast custom hardware SPI implementation. The -SdFatLibSpi class uses the standard Arduino SPI library. The SdFatSoftSpi -class uses software SPI. +The SdFat, SdFatEX, SdFatSoftSpi and SdFatSoftSpiEX classes maintain a +FAT volume, a current working directory, and simplify initialization +of other classes. The SdFat and SdFatEX classes uses a fast custom hardware SPI +implementation. The SdFatSoftSpi and SdFatSoftSpiEX classes uses software SPI. + +the SdFatEX and SdFatSoftSpiEX use extended multi-block I/O for enhanced +performance. These classes must have exclusive use of the SPI bus. The SdBaseFile class provides basic file access functions such as open(), binary read(), binary write(), close(), remove(), and sync(). SdBaseFile @@ -102,19 +104,22 @@ Long %File Names. Long %File names require extra flash but no extra RAM. Opening Long %File Names can be slower than opening Short %File Names. Data read and write performance is not changed by the type of %File Name. -Set SD_SPI_CONFIGURATION to enable various SPI options. The SdFatSoftSpi -and SdFatLibSpi classes can be enabled. SdFatLibSpi uses the standard -Arduino SPI library and SdFatSoftSpi uses software SPI. +If the symbol ENABLE_EXTENDED_TRANSFER_CLASS is nonzero, the class SdFatEX +will be defined. If the symbol ENABLE_SOFTWARE_SPI_CLASS is also nonzero, +the class SdFatSoftSpiEX will be defined. +These classes used extended multi-block SD I/O for better performance. +the SPI bus may not be shared with other devices in this mode. + +Set USE_STANDARD_SPI_LIBRARY and ENABLE_SOFTWARE_SPI_CLASS to +enable various SPI options. set USE_STANDARD_SPI_LIBRARY to use the standard +Arduino SPI library. set ENABLE_SOFTWARE_SPI_CLASS to enable the SdFatSoftSpi +class which uses software SPI. 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_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_TRANSACTIONS is nonzero. - \section SDPath Paths and Working Directories Relative paths in SdFat are resolved in a manner similar to Windows. @@ -352,7 +357,11 @@ getline - Example of getline from section 27.7.1.3 of the C++ standard. LongFileName - Example use of openNext, printName, and open by index. -LowLatencyLogger - A modifiable data logger for higher data rates. +LowLatencyLogger - A data logger for higher data rates. ADC version. + +LowLatencyLoggerADXL345 - A data logger for higher data rates. ADXL345 SPI. + +LowLatencyLoggerMPU6050 - A data logger for higher data rates. MPU6050 I2C. OpenNext - Open all files in the root dir and print their filename. @@ -370,8 +379,6 @@ 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. - rename - A demo of SdFat::rename(old, new) and SdFile::rename(dirFile, newPath). SdFormatter - This program will format an SD or SDHC card. @@ -382,8 +389,6 @@ SdInfo - Initialize an SD card and analyze its structure for trouble shooting. StdioBench - Demo and test of stdio style stream. -ThreeCards - Demonstrate simultaneous use of SdFat, SdFatLibSpi, SdFatSoftSpi. - Timestamp - Sets file create, modify, and access timestamps. TwoCards - Example using two SD cards. diff --git a/SdFat.html b/extras/SdFat.html similarity index 100% rename from SdFat.html rename to extras/SdFat.html diff --git a/SdFatTestSuite/SdFatTestSuite.cpp b/extras/SdFatTestSuite/SdFatTestSuite.cpp similarity index 100% rename from SdFatTestSuite/SdFatTestSuite.cpp rename to extras/SdFatTestSuite/SdFatTestSuite.cpp diff --git a/SdFatTestSuite/SdFatTestSuite.h b/extras/SdFatTestSuite/SdFatTestSuite.h similarity index 100% rename from SdFatTestSuite/SdFatTestSuite.h rename to extras/SdFatTestSuite/SdFatTestSuite.h diff --git a/SdFatTestSuite/examples/ATS_SD_File/ATS_SD_File.ino b/extras/SdFatTestSuite/examples/ATS_SD_File/ATS_SD_File.ino similarity index 100% rename from SdFatTestSuite/examples/ATS_SD_File/ATS_SD_File.ino rename to extras/SdFatTestSuite/examples/ATS_SD_File/ATS_SD_File.ino diff --git a/SdFatTestSuite/examples/ATS_SD_Files/ATS_SD_Files.ino b/extras/SdFatTestSuite/examples/ATS_SD_Files/ATS_SD_Files.ino similarity index 100% rename from SdFatTestSuite/examples/ATS_SD_Files/ATS_SD_Files.ino rename to extras/SdFatTestSuite/examples/ATS_SD_Files/ATS_SD_Files.ino diff --git a/SdFatTestSuite/examples/ATS_SD_Seek/ATS_SD_Seek.ino b/extras/SdFatTestSuite/examples/ATS_SD_Seek/ATS_SD_Seek.ino similarity index 100% rename from SdFatTestSuite/examples/ATS_SD_Seek/ATS_SD_Seek.ino rename to extras/SdFatTestSuite/examples/ATS_SD_Seek/ATS_SD_Seek.ino diff --git a/SdFatTestSuite/examples/StressTest/StressTest.ino b/extras/SdFatTestSuite/examples/StressTest/StressTest.ino similarity index 100% rename from SdFatTestSuite/examples/StressTest/StressTest.ino rename to extras/SdFatTestSuite/examples/StressTest/StressTest.ino diff --git a/SdFatTestSuite/examples/TestMkdir/TestMkdir.ino b/extras/SdFatTestSuite/examples/TestMkdir/TestMkdir.ino similarity index 100% rename from SdFatTestSuite/examples/TestMkdir/TestMkdir.ino rename to extras/SdFatTestSuite/examples/TestMkdir/TestMkdir.ino diff --git a/SdFatTestSuite/examples/TestRmdir/TestRmdir.ino b/extras/SdFatTestSuite/examples/TestRmdir/TestRmdir.ino similarity index 100% rename from SdFatTestSuite/examples/TestRmdir/TestRmdir.ino rename to extras/SdFatTestSuite/examples/TestRmdir/TestRmdir.ino diff --git a/SdFatTestSuite/examples/fstreamTest/fstreamTest.ino b/extras/SdFatTestSuite/examples/fstreamTest/fstreamTest.ino similarity index 100% rename from SdFatTestSuite/examples/fstreamTest/fstreamTest.ino rename to extras/SdFatTestSuite/examples/fstreamTest/fstreamTest.ino diff --git a/SdFatTestSuite/examples/istreamTest/istreamTest.ino b/extras/SdFatTestSuite/examples/istreamTest/istreamTest.ino similarity index 100% rename from SdFatTestSuite/examples/istreamTest/istreamTest.ino rename to extras/SdFatTestSuite/examples/istreamTest/istreamTest.ino diff --git a/SdFatTestSuite/examples/lfnSize/lfnSize.ino b/extras/SdFatTestSuite/examples/lfnSize/lfnSize.ino similarity index 100% rename from SdFatTestSuite/examples/lfnSize/lfnSize.ino rename to extras/SdFatTestSuite/examples/lfnSize/lfnSize.ino diff --git a/SdFatTestSuite/examples/lfnTest/lfnTest.ino b/extras/SdFatTestSuite/examples/lfnTest/lfnTest.ino similarity index 100% rename from SdFatTestSuite/examples/lfnTest/lfnTest.ino rename to extras/SdFatTestSuite/examples/lfnTest/lfnTest.ino diff --git a/SdFatTestSuite/examples/lfnTestCout/lfnTestCout.ino b/extras/SdFatTestSuite/examples/lfnTestCout/lfnTestCout.ino similarity index 100% rename from SdFatTestSuite/examples/lfnTestCout/lfnTestCout.ino rename to extras/SdFatTestSuite/examples/lfnTestCout/lfnTestCout.ino diff --git a/SdFatTestSuite/examples/ostreamTest/ostreamTest.ino b/extras/SdFatTestSuite/examples/ostreamTest/ostreamTest.ino similarity index 100% rename from SdFatTestSuite/examples/ostreamTest/ostreamTest.ino rename to extras/SdFatTestSuite/examples/ostreamTest/ostreamTest.ino diff --git a/changes.txt b/extras/changes.txt similarity index 92% rename from changes.txt rename to extras/changes.txt index a9a7d9da..b71dbd82 100644 --- a/changes.txt +++ b/extras/changes.txt @@ -1,3 +1,40 @@ +13 Sep 2016 + +Added SdFatSdioEX class with Extended SD I/O. + +5 Sep 2016 + +Restructured classes to support SPI and SDIO controllers. + +Support for Teensy 3.5/3.6 SDIO. + +Added TeensySdioDemo example. + +15 Aug 2016 + +New classes SdFatEX and SdFatSoftSpiEX with Extended SD I/O. +These classes provide higher performance but require a dedicated +SPI port. + +The symbol SD_SPI_CONFIGURATION has been replaced by three symbols, +ENABLE_EXTENDED_TRANSFER_CLASS, USE_STANDARD_SPI_LIBRARY, and +ENABLE_SOFTWARE_SPI_CLASS to define the SPI configuration. + +SPI transactions are always used. + +The SPI divisor has been replaced by SPISettings. A new macro +is used to generate SPISettings. This call will use the highest +speed supported by the board that is not over 50 MHz. + + sd.begin(CS_PIN, SD_SCK_MHZ(50)); + +SdFat on STM32 now supports a SdFat constructor with the SPI +port number. See the STM32Test example for sample use. + +New versions of LowLatencyLogger for ADC, ADXL345, and MPU6050. + +Many internal changes to simplify ports to RTOS. + 19 jul 2016 Fix for multi-block transfers chip select. diff --git a/html/_arduino_files_8h.html b/extras/html/_arduino_files_8h.html similarity index 90% rename from html/_arduino_files_8h.html rename to extras/html/_arduino_files_8h.html index 137d110a..5be7a67f 100644 --- a/html/_arduino_files_8h.html +++ b/extras/html/_arduino_files_8h.html @@ -38,7 +38,6 @@
@@ -168,7 +169,7 @@
diff --git a/html/_arduino_files_8h__dep__incl.png b/extras/html/_arduino_files_8h__dep__incl.png similarity index 100% rename from html/_arduino_files_8h__dep__incl.png rename to extras/html/_arduino_files_8h__dep__incl.png diff --git a/extras/html/_arduino_files_8h__incl.png b/extras/html/_arduino_files_8h__incl.png new file mode 100644 index 00000000..2c4c69f4 Binary files /dev/null and b/extras/html/_arduino_files_8h__incl.png differ diff --git a/html/_arduino_stream_8h.html b/extras/html/_arduino_stream_8h.html similarity index 81% rename from html/_arduino_stream_8h.html rename to extras/html/_arduino_stream_8h.html index c936e38f..1f3c9f95 100644 --- a/html/_arduino_stream_8h.html +++ b/extras/html/_arduino_stream_8h.html @@ -38,7 +38,6 @@
@@ -215,6 +201,19 @@

Allow FAT12 volumes if FAT12_SUPPORT is non-zero. FAT12 has not been well tested.

+
+
+ +
+
+ + + + +
#define MAINTAIN_FREE_CLUSTER_COUNT   0
+
+

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.

+
@@ -267,7 +266,7 @@
diff --git a/extras/html/_fat_lib_config_8h__dep__incl.png b/extras/html/_fat_lib_config_8h__dep__incl.png new file mode 100644 index 00000000..a7a8d212 Binary files /dev/null and b/extras/html/_fat_lib_config_8h__dep__incl.png differ diff --git a/extras/html/_fat_lib_config_8h__incl.png b/extras/html/_fat_lib_config_8h__incl.png new file mode 100644 index 00000000..4f0dc511 Binary files /dev/null and b/extras/html/_fat_lib_config_8h__incl.png differ diff --git a/html/_fat_structs_8h.html b/extras/html/_fat_structs_8h.html similarity index 82% rename from html/_fat_structs_8h.html rename to extras/html/_fat_structs_8h.html index 042aa4a7..a3a887f8 100644 --- a/html/_fat_structs_8h.html +++ b/extras/html/_fat_structs_8h.html @@ -38,7 +38,6 @@ @@ -196,64 +195,64 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -843,12 +842,12 @@

Function Documentation

Variable Documentation

- +

Variables

uint8_t const BOOTSIG0 = 0X55
 
uint8_t const BOOTSIG1 = 0XAA
 
uint8_t const DIR_ATT_ARCHIVE = 0X20
 
uint8_t const DIR_ATT_DEFINED_BITS = 0X3F
 
uint8_t const DIR_ATT_DIRECTORY = 0X10
 
uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY)
 
uint8_t const DIR_ATT_HIDDEN = 0X02
 
uint8_t const DIR_ATT_LONG_NAME = 0X0F
 
uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F
 
uint8_t const DIR_ATT_READ_ONLY = 0X01
 
uint8_t const DIR_ATT_SYSTEM = 0X04
 
uint8_t const DIR_ATT_VOLUME_ID = 0X08
 
uint8_t const DIR_NAME_0XE5 = 0X05
 
uint8_t const DIR_NAME_DELETED = 0XE5
 
uint8_t const DIR_NAME_FREE = 0X00
 
const uint8_t BOOTSIG0 = 0X55
 
const uint8_t BOOTSIG1 = 0XAA
 
const uint8_t DIR_ATT_ARCHIVE = 0X20
 
const uint8_t DIR_ATT_DEFINED_BITS = 0X3F
 
const uint8_t DIR_ATT_DIRECTORY = 0X10
 
const uint8_t DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY)
 
const uint8_t DIR_ATT_HIDDEN = 0X02
 
const uint8_t DIR_ATT_LONG_NAME = 0X0F
 
const uint8_t DIR_ATT_LONG_NAME_MASK = 0X3F
 
const uint8_t DIR_ATT_READ_ONLY = 0X01
 
const uint8_t DIR_ATT_SYSTEM = 0X04
 
const uint8_t DIR_ATT_VOLUME_ID = 0X08
 
const uint8_t DIR_NAME_0XE5 = 0X05
 
const uint8_t DIR_NAME_DELETED = 0XE5
 
const uint8_t DIR_NAME_FREE = 0X00
 
const uint8_t DIR_NT_LC_BASE = 0X08
 
const uint8_t DIR_NT_LC_EXT = 0X10
 
uint8_t const EXTENDED_BOOT_SIG = 0X29
 
uint16_t const FAT12EOC = 0XFFF
 
uint16_t const FAT12EOC_MIN = 0XFF8
 
uint16_t const FAT16EOC = 0XFFFF
 
uint16_t const FAT16EOC_MIN = 0XFFF8
 
uint32_t const FAT32EOC = 0X0FFFFFFF
 
uint32_t const FAT32EOC_MIN = 0X0FFFFFF8
 
uint32_t const FAT32MASK = 0X0FFFFFFF
 
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1
 
uint16_t const FAT_DEFAULT_TIME = (1 << 11)
 
uint32_t const FSINFO_LEAD_SIG = 0x41615252
 
uint32_t const FSINFO_STRUCT_SIG = 0x61417272
 
const uint8_t EXTENDED_BOOT_SIG = 0X29
 
const uint16_t FAT12EOC = 0XFFF
 
const uint16_t FAT12EOC_MIN = 0XFF8
 
const uint16_t FAT16EOC = 0XFFFF
 
const uint16_t FAT16EOC_MIN = 0XFFF8
 
const uint32_t FAT32EOC = 0X0FFFFFFF
 
const uint32_t FAT32EOC_MIN = 0X0FFFFFF8
 
const uint32_t FAT32MASK = 0X0FFFFFFF
 
const uint16_t FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1
 
const uint16_t FAT_DEFAULT_TIME = (1 << 11)
 
const uint32_t FSINFO_LEAD_SIG = 0x41615252
 
const uint32_t FSINFO_STRUCT_SIG = 0x61417272
 
const uint8_t LDIR_NAME1_DIM = 5
 
const uint8_t LDIR_NAME2_DIM = 6
- +
uint8_t const BOOTSIG0 = 0X55const uint8_t BOOTSIG0 = 0X55
@@ -856,12 +855,12 @@

Variable Documentation

- +
- +
uint8_t const BOOTSIG1 = 0XAAconst uint8_t BOOTSIG1 = 0XAA
@@ -869,12 +868,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_ARCHIVE = 0X20const uint8_t DIR_ATT_ARCHIVE = 0X20
@@ -882,12 +881,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_DEFINED_BITS = 0X3Fconst uint8_t DIR_ATT_DEFINED_BITS = 0X3F
@@ -895,12 +894,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_DIRECTORY = 0X10const uint8_t DIR_ATT_DIRECTORY = 0X10
@@ -908,12 +907,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY)const uint8_t DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY)
@@ -921,12 +920,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_HIDDEN = 0X02const uint8_t DIR_ATT_HIDDEN = 0X02
@@ -934,12 +933,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_LONG_NAME = 0X0Fconst uint8_t DIR_ATT_LONG_NAME = 0X0F
@@ -947,12 +946,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3Fconst uint8_t DIR_ATT_LONG_NAME_MASK = 0X3F
@@ -960,12 +959,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_READ_ONLY = 0X01const uint8_t DIR_ATT_READ_ONLY = 0X01
@@ -973,12 +972,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_SYSTEM = 0X04const uint8_t DIR_ATT_SYSTEM = 0X04
@@ -986,12 +985,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_ATT_VOLUME_ID = 0X08const uint8_t DIR_ATT_VOLUME_ID = 0X08
@@ -999,12 +998,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_NAME_0XE5 = 0X05const uint8_t DIR_NAME_0XE5 = 0X05
@@ -1012,12 +1011,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_NAME_DELETED = 0XE5const uint8_t DIR_NAME_DELETED = 0XE5
@@ -1025,12 +1024,12 @@

Variable Documentation

- +
- +
uint8_t const DIR_NAME_FREE = 0X00const uint8_t DIR_NAME_FREE = 0X00
@@ -1064,12 +1063,12 @@

Variable Documentation

- +
- +
uint8_t const EXTENDED_BOOT_SIG = 0X29const uint8_t EXTENDED_BOOT_SIG = 0X29
@@ -1077,12 +1076,12 @@

Variable Documentation

- +
- +
uint16_t const FAT12EOC = 0XFFFconst uint16_t FAT12EOC = 0XFFF
@@ -1090,12 +1089,12 @@

Variable Documentation

- +
- +
uint16_t const FAT12EOC_MIN = 0XFF8const uint16_t FAT12EOC_MIN = 0XFF8
@@ -1103,12 +1102,12 @@

Variable Documentation

- +
- +
uint16_t const FAT16EOC = 0XFFFFconst uint16_t FAT16EOC = 0XFFFF
@@ -1116,12 +1115,12 @@

Variable Documentation

- +
- +
uint16_t const FAT16EOC_MIN = 0XFFF8const uint16_t FAT16EOC_MIN = 0XFFF8
@@ -1129,12 +1128,12 @@

Variable Documentation

- +
- +
uint32_t const FAT32EOC = 0X0FFFFFFFconst uint32_t FAT32EOC = 0X0FFFFFFF
@@ -1142,12 +1141,12 @@

Variable Documentation

- +
- +
uint32_t const FAT32EOC_MIN = 0X0FFFFFF8const uint32_t FAT32EOC_MIN = 0X0FFFFFF8
@@ -1155,12 +1154,12 @@

Variable Documentation

- +
- +
uint32_t const FAT32MASK = 0X0FFFFFFFconst uint32_t FAT32MASK = 0X0FFFFFFF
@@ -1168,12 +1167,12 @@

Variable Documentation

- +
- +
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1const uint16_t FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1
@@ -1181,12 +1180,12 @@

Variable Documentation

- +
- +
uint16_t const FAT_DEFAULT_TIME = (1 << 11)const uint16_t FAT_DEFAULT_TIME = (1 << 11)
@@ -1194,12 +1193,12 @@

Variable Documentation

- +
- +
uint32_t const FSINFO_LEAD_SIG = 0x41615252const uint32_t FSINFO_LEAD_SIG = 0x41615252
@@ -1207,12 +1206,12 @@

Variable Documentation

- +
- +
uint32_t const FSINFO_STRUCT_SIG = 0x61417272const uint32_t FSINFO_STRUCT_SIG = 0x61417272
@@ -1275,7 +1274,7 @@

Variable Documentation

diff --git a/extras/html/_fat_structs_8h__dep__incl.png b/extras/html/_fat_structs_8h__dep__incl.png new file mode 100644 index 00000000..716eee93 Binary files /dev/null and b/extras/html/_fat_structs_8h__dep__incl.png differ diff --git a/html/_fat_volume_8h.html b/extras/html/_fat_volume_8h.html similarity index 86% rename from html/_fat_volume_8h.html rename to extras/html/_fat_volume_8h.html index 1c12e019..86746853 100644 --- a/html/_fat_volume_8h.html +++ b/extras/html/_fat_volume_8h.html @@ -38,7 +38,6 @@ - +
- +
#define IMPLEMENT_SPI_INTERFACE_SELECTION   0#define IMPLEMENT_SPI_PORT_SELECTION   0
-

Check if API to select HW SPI interface is needed.

+

Check if API to select HW SPI port is needed.

@@ -277,42 +273,12 @@
- +
#define SD_HAS_CUSTOM_SPI   1#define SD_HAS_CUSTOM_SPI   0

Determine the default SPI configuration.

-
-
- -
-
- - - - -
#define SD_SPI_CONFIGURATION   0
-
-

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 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.

-

If SD_SPI_CONFIGURATION is define to be two, only the SdFat class is define and SdFat uses software SPI on the pins defined below.

-

If SD_SPI_CONFIGURATION is define to be three, the three classes, SdFat, SdFatLibSpi, and SdFatSoftSpi are defined. SdFat uses the fast custom SPI implementation. SdFatLibSpi uses the standard Arduino SPI library. SdFatSoftSpi is a template class that uses Software SPI. The template parameters define the software SPI pins. See the ThreeCard example for simultaneous use of all three classes.

- -
-
- -
-
- - - - -
#define SPI_INTERFACE_COUNT   1
-
-

Number of hardware interfaces.

-
@@ -377,78 +343,37 @@ - -
-
- - - - -
#define WDT_YIELD_TIME_MICROS   0
-
-

Handle Watchdog Timer for WiFi modules.

-

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.

- -
-
-

Variable Documentation

- -
-
- - - - -
uint8_t const SOFT_SPI_MISO_PIN = 12
-
-

Software SPI Master In Slave Out pin

- -
-
- +
- +
uint8_t const SOFT_SPI_MOSI_PIN = 11#define USE_STANDARD_SPI_LIBRARY   0
-

If SD_SPI_CONFIGURATION is defined to be two, these definitions will define the pins used for software SPI.

-

The default definition allows Uno shields to be used on other boards.Software SPI Master Out Slave In pin

+

If the symbol USE_STANDARD_SPI_LIBRARY is nonzero, the classes SdFat and SdFatEX use the standard Arduino SPI.h library. If USE_STANDARD_SPI_LIBRARY is zero, an optimized custom SPI driver is used if it exists.

- -
-
- - - - -
uint8_t const SOFT_SPI_SCK_PIN = 13
-
-

Software SPI Clock pin

- -
-
- +
- +
const uint8_t SPI_SCK_INIT_DIVISOR = 128#define WDT_YIELD_TIME_MICROS   0
-

SPI SCK divisor for SD initialization commands. or greater

+

Handle Watchdog Timer for WiFi modules.

+

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.

diff --git a/extras/html/_sd_fat_config_8h__dep__incl.png b/extras/html/_sd_fat_config_8h__dep__incl.png new file mode 100644 index 00000000..2d404277 Binary files /dev/null and b/extras/html/_sd_fat_config_8h__dep__incl.png differ diff --git a/html/_sd_fat_config_8h__incl.png b/extras/html/_sd_fat_config_8h__incl.png similarity index 100% rename from html/_sd_fat_config_8h__incl.png rename to extras/html/_sd_fat_config_8h__incl.png diff --git a/html/_sd_spi_card_8h.html b/extras/html/_sd_spi_card_8h.html similarity index 65% rename from html/_sd_spi_card_8h.html rename to extras/html/_sd_spi_card_8h.html index 90219338..cdb1ba28 100644 --- a/html/_sd_spi_card_8h.html +++ b/extras/html/_sd_spi_card_8h.html @@ -4,7 +4,7 @@ -SdFat: Arduino/libraries/SdFat/src/SdSpiCard/SdSpiCard.h File Reference +SdFat: Arduino/libraries/SdFat/src/SdCard/SdSpiCard.h File Reference @@ -38,7 +38,6 @@
@@ -94,44 +93,56 @@

SdSpiCard class for V2 SD/SDHC cards. More...

-
#include "SystemInclude.h"
-#include "SdFatConfig.h"
+
#include <stddef.h>
+#include "SysCall.h"
#include "SdInfo.h"
-#include "SdSpi.h"
+#include "../FatLib/BaseBlockDriver.h"
+#include "../SpiDriver/SdSpiDriver.h"
Include dependency graph for SdSpiCard.h:
-
- - - +
+ +
This graph shows which files directly or indirectly include this file:
-
- - - +
+ + + + + + + + + + + + + + +
- - - + + +

Classes

class  Sd2Card
 Raw access to SD and SDHC card using default SPI library. More...
 
class  SdSpiCard
 Raw access to SD and SDHC flash memory cards via SPI protocol. More...
 
class  SdSpiCardEX
 Extended SD I/O block driver. More...
 

Detailed Description

SdSpiCard class for V2 SD/SDHC cards.

diff --git a/extras/html/_sd_spi_card_8h__dep__incl.png b/extras/html/_sd_spi_card_8h__dep__incl.png new file mode 100644 index 00000000..b14e65c6 Binary files /dev/null and b/extras/html/_sd_spi_card_8h__dep__incl.png differ diff --git a/extras/html/_sd_spi_card_8h__incl.png b/extras/html/_sd_spi_card_8h__incl.png new file mode 100644 index 00000000..5ae683e0 Binary files /dev/null and b/extras/html/_sd_spi_card_8h__incl.png differ diff --git a/html/_stdio_stream_8h.html b/extras/html/_stdio_stream_8h.html similarity index 92% rename from html/_stdio_stream_8h.html rename to extras/html/_stdio_stream_8h.html index 51abea67..b157a410 100644 --- a/html/_stdio_stream_8h.html +++ b/extras/html/_stdio_stream_8h.html @@ -38,7 +38,6 @@ @@ -237,7 +238,7 @@

Variable Documentation

diff --git a/extras/html/_stdio_stream_8h__incl.png b/extras/html/_stdio_stream_8h__incl.png new file mode 100644 index 00000000..d49df802 Binary files /dev/null and b/extras/html/_stdio_stream_8h__incl.png differ diff --git a/html/_sys_call_8h.html b/extras/html/_sys_call_8h.html similarity index 64% rename from html/_sys_call_8h.html rename to extras/html/_sys_call_8h.html index 5beeb320..f5e65c89 100644 --- a/html/_sys_call_8h.html +++ b/extras/html/_sys_call_8h.html @@ -4,7 +4,7 @@ -SdFat: Arduino/libraries/SdFat/src/FatLib/SysCall.h File Reference +SdFat: Arduino/libraries/SdFat/src/SysCall.h File Reference @@ -38,7 +38,6 @@
SysCall.h File Reference
@@ -98,20 +98,24 @@
This graph shows which files directly or indirectly include this file:
-
- - - - - - - - - - - - - +
+ + + + + + + + + + + + + + + + +
@@ -125,6 +129,11 @@ Macros +
#define F(str)   (str)
 
+ + +

+Functions

uint16_t curTimeMS ()
 

Detailed Description

SysCall class.

@@ -144,12 +153,37 @@

Define macro for strings stored in flash.

+
+
+

Function Documentation

+ +
+
+ + + + + +
+ + + + + + + +
uint16_t curTimeMS ()
+
+inline
+
+
Returns
the time in milliseconds.
+
diff --git a/extras/html/_sys_call_8h__dep__incl.png b/extras/html/_sys_call_8h__dep__incl.png new file mode 100644 index 00000000..f63dedae Binary files /dev/null and b/extras/html/_sys_call_8h__dep__incl.png differ diff --git a/html/annotated.html b/extras/html/annotated.html similarity index 69% rename from html/annotated.html rename to extras/html/annotated.html index a6ec6914..151eb0e7 100644 --- a/html/annotated.html +++ b/extras/html/annotated.html @@ -38,7 +38,6 @@ diff --git a/html/arrowdown.png b/extras/html/arrowdown.png similarity index 100% rename from html/arrowdown.png rename to extras/html/arrowdown.png diff --git a/html/arrowright.png b/extras/html/arrowright.png similarity index 100% rename from html/arrowright.png rename to extras/html/arrowright.png diff --git a/html/bc_s.png b/extras/html/bc_s.png similarity index 100% rename from html/bc_s.png rename to extras/html/bc_s.png diff --git a/html/bdwn.png b/extras/html/bdwn.png similarity index 100% rename from html/bdwn.png rename to extras/html/bdwn.png diff --git a/html/bufstream_8h.html b/extras/html/bufstream_8h.html similarity index 85% rename from html/bufstream_8h.html rename to extras/html/bufstream_8h.html index 01363b93..f0daa273 100644 --- a/html/bufstream_8h.html +++ b/extras/html/bufstream_8h.html @@ -38,7 +38,6 @@
@@ -119,6 +120,7 @@
+
@@ -136,7 +138,7 @@ diff --git a/extras/html/bufstream_8h__dep__incl.png b/extras/html/bufstream_8h__dep__incl.png new file mode 100644 index 00000000..34df0328 Binary files /dev/null and b/extras/html/bufstream_8h__dep__incl.png differ diff --git a/extras/html/bufstream_8h__incl.png b/extras/html/bufstream_8h__incl.png new file mode 100644 index 00000000..fa0c87bd Binary files /dev/null and b/extras/html/bufstream_8h__incl.png differ diff --git a/html/class_arduino_in_stream-members.html b/extras/html/class_arduino_in_stream-members.html similarity index 99% rename from html/class_arduino_in_stream-members.html rename to extras/html/class_arduino_in_stream-members.html index b807e99c..d875aad0 100644 --- a/html/class_arduino_in_stream-members.html +++ b/extras/html/class_arduino_in_stream-members.html @@ -38,7 +38,6 @@
diff --git a/html/class_arduino_in_stream.html b/extras/html/class_arduino_in_stream.html similarity index 99% rename from html/class_arduino_in_stream.html rename to extras/html/class_arduino_in_stream.html index 921e9d69..9ece8723 100644 --- a/html/class_arduino_in_stream.html +++ b/extras/html/class_arduino_in_stream.html @@ -38,7 +38,6 @@ diff --git a/html/class_arduino_in_stream__coll__graph.png b/extras/html/class_arduino_in_stream__coll__graph.png similarity index 100% rename from html/class_arduino_in_stream__coll__graph.png rename to extras/html/class_arduino_in_stream__coll__graph.png diff --git a/html/class_arduino_in_stream__inherit__graph.png b/extras/html/class_arduino_in_stream__inherit__graph.png similarity index 100% rename from html/class_arduino_in_stream__inherit__graph.png rename to extras/html/class_arduino_in_stream__inherit__graph.png diff --git a/html/class_arduino_out_stream-members.html b/extras/html/class_arduino_out_stream-members.html similarity index 99% rename from html/class_arduino_out_stream-members.html rename to extras/html/class_arduino_out_stream-members.html index b357cc05..e96250f5 100644 --- a/html/class_arduino_out_stream-members.html +++ b/extras/html/class_arduino_out_stream-members.html @@ -38,7 +38,6 @@ diff --git a/html/class_arduino_out_stream.html b/extras/html/class_arduino_out_stream.html similarity index 99% rename from html/class_arduino_out_stream.html rename to extras/html/class_arduino_out_stream.html index 164f7424..badb5a37 100644 --- a/html/class_arduino_out_stream.html +++ b/extras/html/class_arduino_out_stream.html @@ -38,7 +38,6 @@ diff --git a/html/class_arduino_out_stream__coll__graph.png b/extras/html/class_arduino_out_stream__coll__graph.png similarity index 100% rename from html/class_arduino_out_stream__coll__graph.png rename to extras/html/class_arduino_out_stream__coll__graph.png diff --git a/html/class_arduino_out_stream__inherit__graph.png b/extras/html/class_arduino_out_stream__inherit__graph.png similarity index 100% rename from html/class_arduino_out_stream__inherit__graph.png rename to extras/html/class_arduino_out_stream__inherit__graph.png diff --git a/html/class_soft_s_p_i-members.html b/extras/html/class_base_block_driver-members.html similarity index 66% rename from html/class_soft_s_p_i-members.html rename to extras/html/class_base_block_driver-members.html index 0148e42b..4c8c0796 100644 --- a/html/class_soft_s_p_i-members.html +++ b/extras/html/class_base_block_driver-members.html @@ -38,7 +38,6 @@
-
SoftSPI< MisoPin, MosiPin, SckPin, Mode > Member List
+
BaseBlockDriver Member List
-

This is the complete list of members for SoftSPI< MisoPin, MosiPin, SckPin, Mode >, including all inherited members.

+

This is the complete list of members for BaseBlockDriver, including all inherited members.

- - - - + + + + +
begin()SoftSPI< MisoPin, MosiPin, SckPin, Mode >inline
receive()SoftSPI< MisoPin, MosiPin, SckPin, Mode >inline
send(uint8_t data)SoftSPI< MisoPin, MosiPin, SckPin, Mode >inline
transfer(uint8_t txData)SoftSPI< MisoPin, MosiPin, SckPin, Mode >inline
readBlock(uint32_t block, uint8_t *dst)=0BaseBlockDriverpure virtual
readBlocks(uint32_t block, uint8_t *dst, size_t nb)=0BaseBlockDriverpure virtual
syncBlocks()=0BaseBlockDriverpure virtual
writeBlock(uint32_t block, const uint8_t *src)=0BaseBlockDriverpure virtual
writeBlocks(uint32_t block, const uint8_t *src, size_t nb)=0BaseBlockDriverpure virtual
diff --git a/extras/html/class_base_block_driver.html b/extras/html/class_base_block_driver.html new file mode 100644 index 00000000..2e54e056 --- /dev/null +++ b/extras/html/class_base_block_driver.html @@ -0,0 +1,352 @@ + + + + + + +SdFat: BaseBlockDriver Class Reference + + + + + + + + + + +
+
+ + + + + + +
+
SdFat +
+
+
+ + + + + + +
+
+ + +
+ +
+ +
+
+ +
+
BaseBlockDriver Class Referenceabstract
+
+
+ +

Base block driver. + More...

+ +

#include <BaseBlockDriver.h>

+
+Inheritance diagram for BaseBlockDriver:
+
+
Inheritance graph
+ + + +
[legend]
+ + + + + + + + + + + + +

+Public Member Functions

virtual bool readBlock (uint32_t block, uint8_t *dst)=0
 
virtual bool readBlocks (uint32_t block, uint8_t *dst, size_t nb)=0
 
virtual bool syncBlocks ()=0
 
virtual bool writeBlock (uint32_t block, const uint8_t *src)=0
 
virtual bool writeBlocks (uint32_t block, const uint8_t *src, size_t nb)=0
 
+

Detailed Description

+

Base block driver.

+

Member Function Documentation

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
virtual bool BaseBlockDriver::readBlock (uint32_t block,
uint8_t * dst 
)
+
+pure virtual
+
+

Read a 512 byte block from an SD card.

+
Parameters
+ + + +
[in]blockLogical block to be read.
[out]dstPointer to the location that will receive the data.
+
+
+
Returns
The value true is returned for success and the value false is returned for failure.
+ +

Implemented in SdioCard.

+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
virtual bool BaseBlockDriver::readBlocks (uint32_t block,
uint8_t * dst,
size_t nb 
)
+
+pure virtual
+
+

Read multiple 512 byte blocks from an SD card.

+
Parameters
+ + + + +
[in]blockLogical block to be read.
[in]nbNumber of blocks to be read.
[out]dstPointer to the location that will receive the data.
+
+
+
Returns
The value true is returned for success and the value false is returned for failure.
+ +

Implemented in SdioCard.

+ +
+
+ +
+
+ + + + + +
+ + + + + + + +
virtual bool BaseBlockDriver::syncBlocks ()
+
+pure virtual
+
+

End multi-block transfer and go to idle state.

Returns
The value true is returned for success and the value false is returned for failure.
+ +

Implemented in SdioCard.

+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
virtual bool BaseBlockDriver::writeBlock (uint32_t block,
const uint8_t * src 
)
+
+pure virtual
+
+

Writes a 512 byte block to an SD card.

+
Parameters
+ + + +
[in]blockLogical block to be written.
[in]srcPointer to the location of the data to be written.
+
+
+
Returns
The value true is returned for success and the value false is returned for failure.
+ +

Implemented in SdioCard.

+ +
+
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
virtual bool BaseBlockDriver::writeBlocks (uint32_t block,
const uint8_t * src,
size_t nb 
)
+
+pure virtual
+
+

Write multiple 512 byte blocks to an SD card.

+
Parameters
+ + + + +
[in]blockLogical block to be written.
[in]nbNumber of blocks to be written.
[in]srcPointer to the location of the data to be written.
+
+
+
Returns
The value true is returned for success and the value false is returned for failure.
+ +

Implemented in SdioCard.

+ +
+
+
The documentation for this class was generated from the following file:
    +
  • Arduino/libraries/SdFat/src/FatLib/BaseBlockDriver.h
  • +
+
+ + + + diff --git a/extras/html/class_base_block_driver__inherit__graph.png b/extras/html/class_base_block_driver__inherit__graph.png new file mode 100644 index 00000000..1a36e514 Binary files /dev/null and b/extras/html/class_base_block_driver__inherit__graph.png differ diff --git a/html/class_fat_cache-members.html b/extras/html/class_fat_cache-members.html similarity index 95% rename from html/class_fat_cache-members.html rename to extras/html/class_fat_cache-members.html index be8d50c4..e9b5f48e 100644 --- a/html/class_fat_cache-members.html +++ b/extras/html/class_fat_cache-members.html @@ -38,7 +38,6 @@ diff --git a/html/class_fat_cache.html b/extras/html/class_fat_cache.html similarity index 93% rename from html/class_fat_cache.html rename to extras/html/class_fat_cache.html index 78e90a1f..2ba6879d 100644 --- a/html/class_fat_cache.html +++ b/extras/html/class_fat_cache.html @@ -38,7 +38,6 @@ diff --git a/html/class_fat_file.html b/extras/html/class_fat_file.html similarity index 97% rename from html/class_fat_file.html rename to extras/html/class_fat_file.html index 387db55c..e9b283fb 100644 --- a/html/class_fat_file.html +++ b/extras/html/class_fat_file.html @@ -38,7 +38,6 @@ @@ -125,6 +125,8 @@ + + @@ -149,6 +151,8 @@ + + @@ -518,7 +522,50 @@

Member Function Documentation

Parameters
 
bool createContiguous (FatFile *dirFile, const char *path, uint32_t size)
 
bool createContiguous (const char *path, uint32_t size)
 
uint32_t curCluster () const
 
uint32_t curPosition () const
 
uint32_t fileSize () const
 
uint32_t firstBlock ()
 
uint32_t firstCluster () const
 
uint8_t getError ()
- + + +
[in]dirFileThe directory where the file will be created.
[in]pathA path with a valid DOS 8.3 file name.
[in]pathA path with a validfile name.
[in]sizeThe desired file size.
+ + +
Returns
The value true is returned for success and the value false, is returned for failure.
+ + + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool FatFile::createContiguous (const char * path,
uint32_t size 
)
+
+inline
+
+

Create and open a new contiguous file of a specified size.

+
Parameters
+ +
[in]pathA path with a validfile name.
[in]sizeThe desired file size.
@@ -940,6 +987,30 @@

Member Function Documentation

Returns
The total number of bytes in a file.
+
+
+ +
+
+ + + + + +
+ + + + + + + +
uint32_t FatFile::firstBlock ()
+
+inline
+
+
Returns
first block of file or zero for empty file.
+
@@ -2910,7 +2981,7 @@

Member Function Documentation

diff --git a/extras/html/class_fat_file__inherit__graph.png b/extras/html/class_fat_file__inherit__graph.png new file mode 100644 index 00000000..6e13b3ca Binary files /dev/null and b/extras/html/class_fat_file__inherit__graph.png differ diff --git a/html/class_fat_file_system-members.html b/extras/html/class_fat_file_system-members.html similarity index 97% rename from html/class_fat_file_system-members.html rename to extras/html/class_fat_file_system-members.html index 4b02c33a..dae8a2ec 100644 --- a/html/class_fat_file_system-members.html +++ b/extras/html/class_fat_file_system-members.html @@ -38,7 +38,6 @@ diff --git a/html/class_fat_file_system.html b/extras/html/class_fat_file_system.html similarity index 96% rename from html/class_fat_file_system.html rename to extras/html/class_fat_file_system.html index 59b16913..ac0b556e 100644 --- a/html/class_fat_file_system.html +++ b/extras/html/class_fat_file_system.html @@ -38,7 +38,6 @@
@@ -100,11 +99,16 @@
Inheritance graph
- - - - - + + + + + + + + + +
[legend]
@@ -155,6 +159,9 @@ + +
class FatFile
 
+class FatFileSystem
 

Detailed Description

Access FAT16 and FAT32 volumes on raw file devices.

@@ -611,7 +618,7 @@

Member Function Documentation

diff --git a/extras/html/class_fat_volume__inherit__graph.png b/extras/html/class_fat_volume__inherit__graph.png new file mode 100644 index 00000000..7773a799 Binary files /dev/null and b/extras/html/class_fat_volume__inherit__graph.png differ diff --git a/html/class_file-members.html b/extras/html/class_file-members.html similarity index 86% rename from html/class_file-members.html rename to extras/html/class_file-members.html index 2a7d7a7c..113bcf6e 100644 --- a/html/class_file-members.html +++ b/extras/html/class_file-members.html @@ -38,7 +38,6 @@ diff --git a/html/class_file.html b/extras/html/class_file.html similarity index 98% rename from html/class_file.html rename to extras/html/class_file.html index 4450ca93..5e32727e 100644 --- a/html/class_file.html +++ b/extras/html/class_file.html @@ -38,7 +38,6 @@ +
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool FatFile::createContiguous (const char * path,
uint32_t size 
)
+
+inlineinherited
+
+

Create and open a new contiguous file of a specified size.

+
Parameters
+ +
[in]pathA path with a validfile name.
[in]sizeThe desired file size.
@@ -991,6 +1037,30 @@

Member Function Documentation

Returns
The total number of bytes in a file.
+
+
+ +
+
+ + + + + +
+ + + + + + + +
uint32_t FatFile::firstBlock ()
+
+inlineinherited
+
+
Returns
first block of file or zero for empty file.
+
@@ -3507,7 +3577,7 @@

Member Function Documentation

diff --git a/html/class_file__coll__graph.png b/extras/html/class_file__coll__graph.png similarity index 100% rename from html/class_file__coll__graph.png rename to extras/html/class_file__coll__graph.png diff --git a/html/class_file__inherit__graph.png b/extras/html/class_file__inherit__graph.png similarity index 100% rename from html/class_file__inherit__graph.png rename to extras/html/class_file__inherit__graph.png diff --git a/html/class_minimum_serial-members.html b/extras/html/class_minimum_serial-members.html similarity index 73% rename from html/class_minimum_serial-members.html rename to extras/html/class_minimum_serial-members.html index eb88bfca..472096df 100644 --- a/html/class_minimum_serial-members.html +++ b/extras/html/class_minimum_serial-members.html @@ -38,7 +38,6 @@ diff --git a/html/class_minimum_serial.html b/extras/html/class_minimum_serial.html similarity index 74% rename from html/class_minimum_serial.html rename to extras/html/class_minimum_serial.html index 26f06903..27b4e056 100644 --- a/html/class_minimum_serial.html +++ b/extras/html/class_minimum_serial.html @@ -38,7 +38,6 @@
+
Returns
one if data is available.
+ +
+
@@ -141,6 +162,46 @@ +
+
+ +
+
+ + + + + + + +
void MinimumSerial::flush ()
+
+

Wait for write done.

+ +
+
+ +
+
+ + + + + +
+ + + + + + + +
MinimumSerial::operator bool ()
+
+inline
+
+
Returns
true for hardware serial
+
@@ -184,13 +245,13 @@
The documentation for this class was generated from the following files:
    -
  • Arduino/libraries/SdFat/src/MinimumSerial.h
  • +
  • Arduino/libraries/SdFat/src/MinimumSerial.h
  • Arduino/libraries/SdFat/src/MinimumSerial.cpp
diff --git a/html/class_minimum_serial__coll__graph.png b/extras/html/class_minimum_serial__coll__graph.png similarity index 100% rename from html/class_minimum_serial__coll__graph.png rename to extras/html/class_minimum_serial__coll__graph.png diff --git a/html/class_minimum_serial__inherit__graph.png b/extras/html/class_minimum_serial__inherit__graph.png similarity index 100% rename from html/class_minimum_serial__inherit__graph.png rename to extras/html/class_minimum_serial__inherit__graph.png diff --git a/html/class_print_file-members.html b/extras/html/class_print_file-members.html similarity index 87% rename from html/class_print_file-members.html rename to extras/html/class_print_file-members.html index 99aab573..44473ffe 100644 --- a/html/class_print_file-members.html +++ b/extras/html/class_print_file-members.html @@ -38,7 +38,6 @@ diff --git a/html/class_print_file.html b/extras/html/class_print_file.html similarity index 97% rename from html/class_print_file.html rename to extras/html/class_print_file.html index eefe22c4..ec56bef1 100644 --- a/html/class_print_file.html +++ b/extras/html/class_print_file.html @@ -38,7 +38,6 @@ + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool FatFile::createContiguous (const char * path,
uint32_t size 
)
+
+inlineinherited
+
+

Create and open a new contiguous file of a specified size.

+
Parameters
+ +
[in]pathA path with a validfile name.
[in]sizeThe desired file size.
@@ -975,6 +1022,30 @@

Member Function Documentation

Returns
The total number of bytes in a file.
+
+
+ +
+
+ + + + + +
+ + + + + + + +
uint32_t FatFile::firstBlock ()
+
+inlineinherited
+
+
Returns
first block of file or zero for empty file.
+
@@ -3283,7 +3354,7 @@

Member Function Documentation

diff --git a/html/class_print_file__coll__graph.png b/extras/html/class_print_file__coll__graph.png similarity index 100% rename from html/class_print_file__coll__graph.png rename to extras/html/class_print_file__coll__graph.png diff --git a/extras/html/class_print_file__inherit__graph.png b/extras/html/class_print_file__inherit__graph.png new file mode 100644 index 00000000..3706975d Binary files /dev/null and b/extras/html/class_print_file__inherit__graph.png differ diff --git a/html/class_sd_spi_card-members.html b/extras/html/class_sd2_card-members.html similarity index 68% rename from html/class_sd_spi_card-members.html rename to extras/html/class_sd2_card-members.html index 9ea9ca9e..0ad99b48 100644 --- a/html/class_sd_spi_card-members.html +++ b/extras/html/class_sd2_card-members.html @@ -38,7 +38,6 @@
-
SdSpiCard Member List
+
Sd2Card Member List
-

This is the complete list of members for SdSpiCard, including all inherited members.

+

This is the complete list of members for Sd2Card, including all inherited members.

- - - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - - - + + + + + + + +
begin(m_spi_t *spi, uint8_t chipSelectPin=SS, uint8_t sckDivisor=SPI_FULL_SPEED)SdSpiCard
cardSize()SdSpiCard
chipSelectHigh()SdSpiCard
chipSelectLow()SdSpiCard
erase(uint32_t firstBlock, uint32_t lastBlock)SdSpiCard
eraseSingleBlockEnable()SdSpiCard
error(uint8_t code)SdSpiCardinline
errorCode() const SdSpiCardinline
errorData() const SdSpiCardinline
isBusy()SdSpiCard
m_spi_t typedefSdSpiCard
readBlock(uint32_t block, uint8_t *dst)SdSpiCard
readBlocks(uint32_t block, uint8_t *dst, size_t count)SdSpiCard
begin(uint8_t csPin=SS, SPISettings settings=SD_SCK_MHZ(50))Sd2Cardinline
SdSpiCard::begin(SdSpiDriver *spi, uint8_t csPin, SPISettings spiSettings)SdSpiCard
cardSize()SdSpiCard
erase(uint32_t firstBlock, uint32_t lastBlock)SdSpiCard
eraseSingleBlockEnable()SdSpiCard
error(uint8_t code)SdSpiCardinline
errorCode() const SdSpiCardinline
errorData() const SdSpiCardinline
isBusy()SdSpiCard
readBlock(uint32_t lba, uint8_t *dst)SdSpiCard
readBlocks(uint32_t lba, uint8_t *dst, size_t nb)SdSpiCard
readCID(cid_t *cid)SdSpiCardinline
readCSD(csd_t *csd)SdSpiCardinline
readData(uint8_t *dst)SdSpiCard
readOCR(uint32_t *ocr)SdSpiCard
readStart(uint32_t blockNumber)SdSpiCard
readStop()SdSpiCard
sckDivisor()SdSpiCardinline
readStatus(uint8_t *status)SdSpiCard
readStop()SdSpiCard
SdSpiCard()SdSpiCardinline
selected()SdSpiCardinline
setSckDivisor(uint8_t sckDivisor)SdSpiCardinline
type() const SdSpiCardinline
writeBlock(uint32_t blockNumber, const uint8_t *src)SdSpiCard
writeBlocks(uint32_t block, const uint8_t *src, size_t count)SdSpiCard
writeData(const uint8_t *src)SdSpiCard
spiStart()SdSpiCard
spiStop()SdSpiCard
syncBlocks()SdSpiCardinline
type() const SdSpiCardinline
writeBlock(uint32_t lba, const uint8_t *src)SdSpiCard
writeBlocks(uint32_t lba, const uint8_t *src, size_t nb)SdSpiCard
writeData(const uint8_t *src)SdSpiCard
writeStart(uint32_t blockNumber)SdSpiCard
writeStart(uint32_t blockNumber, uint32_t eraseCount)SdSpiCard
writeStop()SdSpiCard
diff --git a/html/class_sd2_card.html b/extras/html/class_sd2_card.html similarity index 81% rename from html/class_sd2_card.html rename to extras/html/class_sd2_card.html index 24b6579c..1ba9a572 100644 --- a/html/class_sd2_card.html +++ b/extras/html/class_sd2_card.html @@ -38,7 +38,6 @@
@@ -94,7 +92,7 @@

Raw access to SD and SDHC card using default SPI library. More...

-

#include <SdSpiCard.h>

+

#include <SdFat.h>

Inheritance diagram for Sd2Card:
@@ -112,21 +110,14 @@
[legend]
- - - -

-Public Types

typedef SpiDefault_t m_spi_t
 
- - + + + + - - - - @@ -137,14 +128,12 @@ - - - - - - + + + + @@ -155,22 +144,26 @@ + + - - - - - - + + + + + + - - - - + + + + + + @@ -178,8 +171,8 @@

Public Member Functions

bool begin (uint8_t chipSelectPin=SS, uint8_t sckDivisor=2)
 
bool begin (SdSpiDriver *spi, uint8_t csPin, SPISettings spiSettings)
 
bool begin (uint8_t csPin=SS, SPISettings settings=SD_SCK_MHZ(50))
 
uint32_t cardSize ()
 
void chipSelectHigh ()
 
void chipSelectLow ()
 
bool erase (uint32_t firstBlock, uint32_t lastBlock)
 
bool eraseSingleBlockEnable ()
 
int errorData () const
 
bool init (uint8_t sckDivisor=2, uint8_t chipSelectPin=SS)
 
bool isBusy ()
 
bool readBlock (uint32_t block, uint8_t *dst)
 
bool readBlocks (uint32_t block, uint8_t *dst, size_t count)
 
bool readBlock (uint32_t lba, uint8_t *dst)
 
bool readBlocks (uint32_t lba, uint8_t *dst, size_t nb)
 
bool readCID (cid_t *cid)
 
bool readCSD (csd_t *csd)
 
bool readStart (uint32_t blockNumber)
 
bool readStatus (uint8_t *status)
 
bool readStop ()
 
uint8_t sckDivisor ()
 
bool selected ()
 
void setSckDivisor (uint8_t sckDivisor)
 
void spiStart ()
 
void spiStop ()
 
bool syncBlocks ()
 
int type () const
 
bool writeBlock (uint32_t blockNumber, const uint8_t *src)
 
bool writeBlocks (uint32_t block, const uint8_t *src, size_t count)
 
bool writeBlock (uint32_t lba, const uint8_t *src)
 
bool writeBlocks (uint32_t lba, const uint8_t *src, size_t nb)
 
bool writeData (const uint8_t *src)
 
bool writeStart (uint32_t blockNumber)
 
bool writeStart (uint32_t blockNumber, uint32_t eraseCount)
 
bool writeStop ()

Detailed Description

Raw access to SD and SDHC card using default SPI library.

-

Member Typedef Documentation

- +

Member Function Documentation

+
@@ -187,7 +180,27 @@ @@ -196,12 +209,19 @@
- + + + + + + + + + + + + + + + + + + + + +
typedef SpiDefault_t SdSpiCard::m_spi_tbool SdSpiCard::begin (SdSpiDriver * spi,
uint8_t csPin,
SPISettings spiSettings 
)
-

typedef for SPI class.

+

Initialize the SD card.

Parameters
+ + + + +
[in]spiSPI driver for card.
[in]csPincard chip select pin.
[in]spiSettingsSPI speed, mode, and bit order.
+
+
+
Returns
true for success else false.
-

Member Function Documentation

- +
@@ -212,13 +232,13 @@

Member Function Documentation

- + - - + + @@ -234,8 +254,8 @@

Member Function Documentation

Initialize the SD card.

Parameters
bool Sd2Card::begin ( uint8_t chipSelectPin = SS, csPin = SS,
uint8_t sckDivisor = 2 SPISettings settings = SD_SCK_MHZ(50) 
- - + +
[in]chipSelectPinSD chip select pin.
[in]sckDivisorSPI clock divisor.
[in]csPinSD chip select pin.
[in]settingsSPI speed, mode, and bit order.
@@ -266,56 +286,6 @@

Member Function Documentation

Determine the size of an SD flash memory card.

Returns
The number of 512 byte data blocks in the card or zero if an error occurs.
-
-
- -
-
- - - - - -
- - - - - - - -
void SdSpiCard::chipSelectHigh ()
-
-inherited
-
-

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 SdSpiCard::chipSelectLow ()
-
-inherited
-
-

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.

-
@@ -437,7 +407,7 @@

Member Function Documentation

-
Returns
code for the last error. See SdSpiCard.h for a list of error codes.
+
Returns
code for the last error. See SdInfo.h for a list of error codes.
@@ -463,48 +433,6 @@

Member Function Documentation

Returns
error data for last error.
-
- - -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
bool Sd2Card::init (uint8_t sckDivisor = 2,
uint8_t chipSelectPin = SS 
)
-
-inline
-
-

Initialize the SD card. Obsolete form.

Parameters
- - - -
[in]chipSelectPinSD chip select pin.
[in]sckDivisorSPI clock divisor.
-
-
-
Returns
true for success else false.
-
@@ -532,7 +460,7 @@

Member Function Documentation

- +
@@ -543,7 +471,7 @@

Member Function Documentation

- + @@ -566,7 +494,7 @@

Member Function Documentation

Read a 512 byte block from an SD card.

Parameters
bool SdSpiCard::readBlock ( uint32_t block, lba,
- +
[in]blockLogical block to be read.
[in]lbaLogical block to be read.
[out]dstPointer to the location that will receive the data.
@@ -575,7 +503,7 @@

Member Function Documentation

- +
@@ -586,7 +514,7 @@

Member Function Documentation

- + @@ -598,7 +526,7 @@

Member Function Documentation

- + @@ -615,8 +543,8 @@

Member Function Documentation

Read multiple 512 byte blocks from an SD card.

Parameters
bool SdSpiCard::readBlocks ( uint32_t block, lba,
size_t count nb 
- - + +
[in]blockLogical block to be read.
[in]countNumber of blocks to be read.
[in]lbaLogical block to be read.
[in]nbNumber of blocks to be read.
[out]dstPointer to the location that will receive the data.
@@ -784,6 +712,37 @@

Member Function Documentation

Note
This function is used with readData() and readStop() for optimized multiple block reads. SPI chipSelect must be low for the entire sequence.
Returns
The value true is returned for success and the value false is returned for failure.
+
+
+ +
+
+ + + + + +
+ + + + + + + + +
bool SdSpiCard::readStatus (uint8_t * status)
+
+inherited
+
+

Return the 64 byte card status

Parameters
+ + +
[out]statuslocation for 64 status bytes.
+
+
+
Returns
The value true is returned for success and the value false is returned for failure.
+
@@ -811,7 +770,7 @@

Member Function Documentation

- +
@@ -819,7 +778,7 @@

Member Function Documentation

+inherited
- + @@ -827,16 +786,15 @@

Member Function Documentation

uint8_t SdSpiCard::sckDivisor void SdSpiCard::spiStart ( )
-inlineinherited
-

Return SCK divisor.

-
Returns
Requested SCK divisor.
+

Set CS low and activate the card.

- +
@@ -844,7 +802,7 @@

Member Function Documentation

+inherited
- + @@ -852,15 +810,15 @@

Member Function Documentation

bool SdSpiCard::selected void SdSpiCard::spiStop ( )
-inlineinherited
-
Returns
the SD chip select status, true if slected else false.
+

Set CS high and deactivate the card.

- +
@@ -868,10 +826,9 @@

Member Function Documentation

- + - - +
void SdSpiCard::setSckDivisor bool SdSpiCard::syncBlocks (uint8_t sckDivisor))
@@ -881,12 +838,7 @@

Member Function Documentation

-

Set SCK divisor.

Parameters
- - -
[in]sckDivisorvalue for divisor.
-
-
+
Returns
success if sync successful. Not for user apps.
@@ -914,7 +866,7 @@

Member Function Documentation

- +
@@ -925,7 +877,7 @@

Member Function Documentation

- + @@ -948,7 +900,7 @@

Member Function Documentation

Writes a 512 byte block to an SD card.

Parameters
bool SdSpiCard::writeBlock ( uint32_t blockNumber, lba,
- +
[in]blockNumberLogical block to be written.
[in]lbaLogical block to be written.
[in]srcPointer to the location of the data to be written.
@@ -957,7 +909,7 @@

Member Function Documentation

- +
@@ -968,7 +920,7 @@

Member Function Documentation

- + @@ -980,7 +932,7 @@

Member Function Documentation

- + @@ -997,8 +949,8 @@

Member Function Documentation

Write multiple 512 byte blocks to an SD card.

Parameters
bool SdSpiCard::writeBlocks ( uint32_t block, lba,
size_t count nb 
- - + +
[in]blockLogical block to be written.
[in]countNumber of blocks to be written.
[in]lbaLogical block to be written.
[in]nbNumber of blocks to be written.
[in]srcPointer to the location of the data to be written.
@@ -1036,6 +988,39 @@

Member Function Documentation

Returns
The value true is returned for success and the value false is returned for failure.
+
+
+ +
+
+ + + + + +
+ + + + + + + + +
bool SdSpiCard::writeStart (uint32_t blockNumber)
+
+inherited
+
+

Start a write multiple blocks sequence.

+
Parameters
+ + +
[in]blockNumberAddress of first block in sequence.
+
+
+
Note
This function is used with writeData() and writeStop() for optimized multiple block writes.
+
Returns
The value true is returned for success and the value false is returned for failure.
+
@@ -1069,7 +1054,7 @@

Member Function Documentation

-

Start a write multiple blocks sequence.

+

Start a write multiple blocks sequence with pre-erase.

Parameters
@@ -1108,12 +1093,12 @@

Member Function Documentation


The documentation for this class was generated from the following file: diff --git a/html/class_sd2_card__coll__graph.png b/extras/html/class_sd2_card__coll__graph.png similarity index 100% rename from html/class_sd2_card__coll__graph.png rename to extras/html/class_sd2_card__coll__graph.png diff --git a/html/class_sd2_card__inherit__graph.png b/extras/html/class_sd2_card__inherit__graph.png similarity index 100% rename from html/class_sd2_card__inherit__graph.png rename to extras/html/class_sd2_card__inherit__graph.png diff --git a/html/class_sd_base_file-members.html b/extras/html/class_sd_base_file-members.html similarity index 87% rename from html/class_sd_base_file-members.html rename to extras/html/class_sd_base_file-members.html index 58697ff6..72f47a42 100644 --- a/html/class_sd_base_file-members.html +++ b/extras/html/class_sd_base_file-members.html @@ -38,7 +38,6 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -181,7 +182,7 @@
[in]blockNumberAddress of first block in sequence.
close()FatFile
contiguousRange(uint32_t *bgnBlock, uint32_t *endBlock)FatFile
createContiguous(FatFile *dirFile, const char *path, uint32_t size)FatFile
curCluster() const FatFileinline
curPosition() const FatFileinline
cwd()FatFileinlinestatic
dateTimeCallback(void(*dateTime)(uint16_t *date, uint16_t *time))FatFileinlinestatic
dateTimeCallbackCancel()FatFileinlinestatic
dirEntry(dir_t *dir)FatFile
dirIndex()FatFileinline
dirName(const dir_t *dir, char *name)FatFilestatic
dirSize()FatFile
dmpFile(print_t *pr, uint32_t pos, size_t n)FatFile
exists(const char *path)FatFileinline
FatFile()FatFileinline
FatFile(const char *path, uint8_t oflag)FatFileinline
fgets(char *str, int16_t num, char *delim=0)FatFile
fileAttr() const FatFileinline
fileSize() const FatFileinline
createContiguous(const char *path, uint32_t size)FatFileinline
curCluster() const FatFileinline
curPosition() const FatFileinline
cwd()FatFileinlinestatic
dateTimeCallback(void(*dateTime)(uint16_t *date, uint16_t *time))FatFileinlinestatic
dateTimeCallbackCancel()FatFileinlinestatic
dirEntry(dir_t *dir)FatFile
dirIndex()FatFileinline
dirName(const dir_t *dir, char *name)FatFilestatic
dirSize()FatFile
dmpFile(print_t *pr, uint32_t pos, size_t n)FatFile
exists(const char *path)FatFileinline
FatFile()FatFileinline
FatFile(const char *path, uint8_t oflag)FatFileinline
fgets(char *str, int16_t num, char *delim=0)FatFile
fileAttr() const FatFileinline
fileSize() const FatFileinline
firstBlock()FatFileinline
firstCluster() const FatFileinline
getError()FatFileinline
getName(char *name, size_t size)FatFile
diff --git a/html/class_sd_base_file.html b/extras/html/class_sd_base_file.html similarity index 97% rename from html/class_sd_base_file.html rename to extras/html/class_sd_base_file.html index 4e229b8c..525c284f 100644 --- a/html/class_sd_base_file.html +++ b/extras/html/class_sd_base_file.html @@ -38,7 +38,6 @@ + + +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool FatFile::createContiguous (const char * path,
uint32_t size 
)
+
+inlineinherited
+
+

Create and open a new contiguous file of a specified size.

+
Parameters
+ +
[in]pathA path with a validfile name.
[in]sizeThe desired file size.
@@ -971,6 +1017,30 @@

Member Function Documentation

Returns
The total number of bytes in a file.
+
+
+ +
+
+ + + + + +
+ + + + + + + +
uint32_t FatFile::firstBlock ()
+
+inlineinherited
+
+
Returns
first block of file or zero for empty file.
+
@@ -3209,7 +3279,7 @@

Member Function Documentation

diff --git a/html/class_sd_base_file__coll__graph.png b/extras/html/class_sd_base_file__coll__graph.png similarity index 100% rename from html/class_sd_base_file__coll__graph.png rename to extras/html/class_sd_base_file__coll__graph.png diff --git a/html/class_sd_base_file__inherit__graph.png b/extras/html/class_sd_base_file__inherit__graph.png similarity index 100% rename from html/class_sd_base_file__inherit__graph.png rename to extras/html/class_sd_base_file__inherit__graph.png diff --git a/html/class_sd_fat-members.html b/extras/html/class_sd_fat-members.html similarity index 61% rename from html/class_sd_fat-members.html rename to extras/html/class_sd_fat-members.html index 1285c03f..4ea22a41 100644 --- a/html/class_sd_fat-members.html +++ b/extras/html/class_sd_fat-members.html @@ -38,7 +38,6 @@ diff --git a/html/class_sd_fat.html b/extras/html/class_sd_fat.html similarity index 78% rename from html/class_sd_fat.html rename to extras/html/class_sd_fat.html index 10632258..96214e79 100644 --- a/html/class_sd_fat.html +++ b/extras/html/class_sd_fat.html @@ -38,7 +38,6 @@