Skip to content

Commit

Permalink
Added Sd.h API and SPI transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
greiman committed Nov 11, 2014
1 parent 1fe7842 commit feeeabc
Show file tree
Hide file tree
Showing 232 changed files with 6,708 additions and 5,339 deletions.
23 changes: 23 additions & 0 deletions SPI_Transactions.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
To enable support for SPI transactions, edit SfFatCinfig.h and modify these
defines.

//------------------------------------------------------------------------------
/**
* Set ENABLE_SPI_TRANSACTION nonzero to enable the SPI transaction feature
* of the standard Arduino SPI library. You must include SPI.h in your
* sketches when ENABLE_SPI_TRANSACTION is nonzero.
*/
#define ENABLE_SPI_TRANSACTION 0
//------------------------------------------------------------------------------
/**
* Set ENABLE_SPI_YIELD nonzero to enable release of the SPI bus during
* SD card busy waits.
*
* This will allow interrupt routines to access the SPI bus if
* ENABLE_SPI_TRANSACTION is nonzero.
*
* Setting ENABLE_SPI_YIELD will introduce some extra overhead and will
* slightly slow transfer rates. A few older SD cards may fail when
* ENABLE_SPI_YIELD is nonzero.
*/
#define ENABLE_SPI_YIELD 0
39 changes: 38 additions & 1 deletion SdFat/Sd2Card.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
*/
#include <Sd2Card.h>
#include <SdSpi.h>
#if !USE_SOFTWARE_SPI && ENABLE_SPI_TRANSACTION
#include <SPI.h>
#endif // !USE_SOFTWARE_SPI && defined(SPI_HAS_TRANSACTION)
// debug trace macro
#define SD_TRACE(m, b)
// #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
Expand Down Expand Up @@ -264,13 +267,26 @@ uint32_t Sd2Card::cardSize() {
}
}
//------------------------------------------------------------------------------
void Sd2Card::spiYield() {
#if ENABLE_SPI_YIELD && !USE_SOFTWARE_SPI && defined(SPI_HAS_TRANSACTION)
chipSelectHigh();
chipSelectLow();
#endif // ENABLE_SPI_YIELD && !USE_SOFTWARE_SPI && defined(SPI_HAS_TRANSACTION)
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectHigh() {
digitalWrite(m_chipSelectPin, HIGH);
// insure MISO goes high impedance
m_spi.send(0XFF);
#if !USE_SOFTWARE_SPI && defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif // !USE_SOFTWARE_SPI && defined(SPI_HAS_TRANSACTION)
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow() {
#if !USE_SOFTWARE_SPI && defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(SPISettings());
#endif // !USE_SOFTWARE_SPI && defined(SPI_HAS_TRANSACTION)
m_spi.init(m_sckDivisor);
digitalWrite(m_chipSelectPin, LOW);
}
Expand Down Expand Up @@ -396,6 +412,7 @@ bool Sd2Card::readData(uint8_t* dst, size_t count) {
error(SD_CARD_ERROR_READ_TIMEOUT);
goto fail;
}
spiYield();
}
if (m_status != DATA_START_BLOCK) {
error(SD_CARD_ERROR_READ);
Expand All @@ -419,6 +436,26 @@ bool Sd2Card::readData(uint8_t* dst, size_t count) {
m_spi.receive();
m_spi.receive();
#endif // USE_SD_CRC
chipSelectHigh();
return true;

fail:
chipSelectHigh();
return false;
}
//------------------------------------------------------------------------------
/** Read OCR register.
*
* \param[out] ocr Value of OCR register.
* \return true for success else false.
*/
bool Sd2Card::readOCR(uint32_t* ocr) {
uint8_t *p = reinterpret_cast<uint8_t*>(ocr);
if (cardCommand(CMD58, 0)) {
error(SD_CARD_ERROR_CMD58);
goto fail;
}
for (uint8_t i = 0; i < 4; i++) p[3-i] = m_spi.receive();

chipSelectHigh();
return true;
Expand Down Expand Up @@ -490,6 +527,7 @@ bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
uint16_t t0 = millis();
while (m_spi.receive() != 0XFF) {
if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
spiYield();
}
return true;

Expand Down Expand Up @@ -563,7 +601,6 @@ bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
#else // USE_SD_CRC
uint16_t crc = 0XFFFF;
#endif // USE_SD_CRC

m_spi.send(token);
m_spi.send(src, 512);
m_spi.send(crc >> 8);
Expand Down
2 changes: 2 additions & 0 deletions SdFat/Sd2Card.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class Sd2Card {
return readRegister(CMD9, csd);
}
bool readData(uint8_t *dst);
bool readOCR(uint32_t* ocr);
bool readStart(uint32_t blockNumber);
bool readStop();
/** Return SCK divisor.
Expand Down Expand Up @@ -186,6 +187,7 @@ class Sd2Card {
bool readRegister(uint8_t cmd, void* buf);
void chipSelectHigh();
void chipSelectLow();
void spiYield();
void type(uint8_t value) {m_type = value;}
bool waitNotBusy(uint16_t timeoutMillis);
bool writeData(uint8_t token, const uint8_t* src);
Expand Down
2 changes: 1 addition & 1 deletion SdFat/SdBaseFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
* successfully opened and is not read only, its length shall be truncated to 0.
*
* WARNING: A given file must not be opened by more than one SdBaseFile object
* of file corruption may occur.
* or file corruption may occur.
*
* \note Directory files must be opened read only. Write and truncation is
* not allowed for directory files.
Expand Down
1 change: 1 addition & 0 deletions SdFat/SdBaseFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ class SdBaseFile {
static void printFatDate(Print* pr, uint16_t fatDate);
static void printFatTime(uint16_t fatTime);
static void printFatTime(Print* pr, uint16_t fatTime);
int printField(float value, char term, uint8_t prec = 2);
int printField(int16_t value, char term);
int printField(uint16_t value, char term);
int printField(int32_t value, char term);
Expand Down
31 changes: 30 additions & 1 deletion SdFat/SdBaseFilePrint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ void SdBaseFile::ls(uint8_t flags) {
* \param[in] indent Amount of space before file name. Used for recursive
* list to indicate subdirectory level.
*/
//------------------------------------------------------------------------------
void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) {
if (!isDir()) {
pr->println(F("bad dir"));
Expand Down Expand Up @@ -207,17 +206,40 @@ static int printFieldT(SdBaseFile* file, char sign, Type value, char term) {
*--str = '\r';
}
}
#ifdef OLD_FMT
do {
Type m = value;
value /= 10;
*--str = '0' + m - 10*value;
} while (value);
#else // OLD_FMT
str = fmtDec(value, str);
#endif // OLD_FMT
if (sign) {
*--str = sign;
}
return file->write(str, &buf[sizeof(buf)] - str);
}
//------------------------------------------------------------------------------
/** Print a number followed by a field terminator.
* \param[in] value The number to be printed.
* \param[in] term The field terminator. Use '\\n' for CR LF.
* \param[in] prec Number of digits after decimal point.
* \return The number of bytes written or -1 if an error occurs.
*/
int SdBaseFile::printField(float value, char term, uint8_t prec) {
char buf[24];
char* str = &buf[sizeof(buf)];
if (term) {
*--str = term;
if (term == '\n') {
*--str = '\r';
}
}
str = fmtFloat(value, str, prec);
return write(str, buf + sizeof(buf) - str);
}
//------------------------------------------------------------------------------
/** Print a number followed by a field terminator.
* \param[in] value The number to be printed.
* \param[in] term The field terminator. Use '\\n' for CR LF.
Expand Down Expand Up @@ -314,6 +336,13 @@ size_t SdBaseFile::printName() {
return printName(SdFat::stdOut());
}
//------------------------------------------------------------------------------
/** Print a file's size.
*
* \param[in] pr Print stream for output.
*
* \return The value one, true, is returned for success and
* the value zero, false, is returned for failure.
*/
size_t SdBaseFile::printFileSize(Print* pr) {
char buf[10];
char *ptr = fmtDec(fileSize(), buf + sizeof(buf));
Expand Down
16 changes: 15 additions & 1 deletion SdFat/SdFat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ void SdFat::ls(const char* path, uint8_t flags) {
//------------------------------------------------------------------------------
/** List the directory contents of the volume working directory.
*
* \param[in] pr Print stream for list.
* \param[in] pr Print stream for the list.
*
* \param[in] flags The inclusive OR of
*
Expand All @@ -162,6 +162,20 @@ void SdFat::ls(Print* pr, uint8_t flags) {
m_vwd.ls(pr, flags);
}
//------------------------------------------------------------------------------
/** List the directory contents of the volume working directory to stdOut.
*
* \param[in] pr Print stream for the list.
*
* \param[in] path directory to list.
*
* \param[in] flags The inclusive OR of
*
* LS_DATE - %Print file modification date
*
* LS_SIZE - %Print file size.
*
* LS_R - Recursive list of subdirectories.
*/
void SdFat::ls(Print* pr, const char* path, uint8_t flags) {
SdBaseFile dir(path, O_READ);
dir.ls(pr, flags);
Expand Down
15 changes: 14 additions & 1 deletion SdFat/SdFat.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define DBG_FAIL_MACRO // Serial.print(__FILE__);Serial.println(__LINE__)
//------------------------------------------------------------------------------
/** SdFat version YYYYMMDD */
#define SD_FAT_VERSION 20140806
#define SD_FAT_VERSION 20141111
//------------------------------------------------------------------------------
/** error if old IDE */
#if !defined(ARDUINO) || ARDUINO < 100
Expand All @@ -37,6 +37,7 @@
//------------------------------------------------------------------------------
#include <SdFile.h>
#include <SdStream.h>
#include <StdioStream.h>
#include <ArduinoStream.h>
#include <MinimumSerial.h>
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -89,6 +90,18 @@ class SdFat {
static void setStdOut(Print* stream) {m_stdOut = stream;}
/** \return Print stream for messages. */
static Print* stdOut() {return m_stdOut;}
//----------------------------------------------------------------------------
/** open a file
*
* \param[in] path location of file to be opened.
* \param[in] mode open mode flags.
* \return a File object.
*/
File open(const char *path, uint8_t mode = FILE_READ) {
File tmpFile;
tmpFile.open(&m_vwd, path, mode);
return tmpFile;
}

private:
Sd2Card m_card;
Expand Down
Loading

0 comments on commit feeeabc

Please sign in to comment.