| @@ -13,7 +13,7 @@ const uint8_t SD_CS_PIN = SS; | |||
| const uint8_t SD_CS_PIN = SDCARD_SS_PIN; | |||
| #endif // SDCARD_SS_PIN | |||
| // Use SPI, SD_CS_PIN, SHARED_SPI, FULL_SPEED. | |||
| // Use SPI, SD_CS_PIN, SHARED_SPI, 50 MHz. | |||
| #define SD_CONFIG SdSpiConfig(SD_CS_PIN) | |||
| SdExFat sd; | |||
| @@ -0,0 +1,47 @@ | |||
| // An example of an external chip select functions. | |||
| // Useful for port expanders or replacement of the standard GPIO functions. | |||
| // | |||
| #include "SdFat.h" | |||
| // SD_CHIP_SELECT_MODE must be set to one or two in SdFat/SdFatConfig.h. | |||
| // A value of one allows optional replacement and two requires replacement. | |||
| #if SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2 | |||
| // SD chip select pin. | |||
| #define SD_CS_PIN SS | |||
| #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(50)) | |||
| SdFat sd; | |||
| // Stats to verify function calls. | |||
| uint32_t initCalls = 0; | |||
| uint32_t writeCalls = 0; | |||
| //------------------------------------------------------------------------------ | |||
| // Modify these functions for your port expander or custom GPIO library. | |||
| void sdCsInit(SdCsPin_t pin) { | |||
| initCalls++; | |||
| pinMode(pin, OUTPUT); | |||
| } | |||
| void sdCsWrite(SdCsPin_t pin, bool level) { | |||
| writeCalls++; | |||
| digitalWrite(pin, level); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void setup() { | |||
| Serial.begin(9600); | |||
| if (!sd.begin(SD_CONFIG)) { | |||
| sd.initErrorHalt(&Serial); | |||
| } | |||
| sd.ls(&Serial, LS_SIZE); | |||
| Serial.print(F("sdCsInit calls: ")); | |||
| Serial.println(initCalls); | |||
| Serial.print(F("sdCsWrite calls: ")); | |||
| Serial.println(writeCalls); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void loop() {} | |||
| #else // SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2 | |||
| #error SD_CHIP_SELECT_MODE must be one or two in SdFat/SdFatConfig.h | |||
| #endif // SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2 | |||
| @@ -0,0 +1,78 @@ | |||
| // An example of an external SPI driver. | |||
| // | |||
| #include "SdFat.h" | |||
| #include "SPI.h" // Only required if you use features in the SPI library. | |||
| #if SPI_DRIVER_SELECT == 3 // Must be set in SdFat/SdFatConfig.h | |||
| // SD chip select pin. | |||
| #define SD_CS_PIN SS | |||
| // This is a simple driver based on the the standard SPI.h library. | |||
| // You can write a driver entirely independent of SPI.h. | |||
| // It can be optimized for your board or a different SPI port can be used. | |||
| // The driver must be derived from SdSpiBaseClass. | |||
| // See: SdFat/src/SpiDriver/SdSpiBaseClass.h | |||
| class MySpiClass : public SdSpiBaseClass { | |||
| public: | |||
| // Activate SPI hardware with correct speed and mode. | |||
| void activate() { | |||
| SPI.beginTransaction(m_spiSettings); | |||
| } | |||
| // Initialize the SPI bus. | |||
| void begin(SdSpiConfig config) { | |||
| (void)config; | |||
| SPI.begin(); | |||
| } | |||
| // Deactivate SPI hardware. | |||
| void deactivate() { | |||
| SPI.endTransaction(); | |||
| } | |||
| // Receive a byte. | |||
| uint8_t receive() { | |||
| return SPI.transfer(0XFF); | |||
| } | |||
| // Receive multiple bytes. | |||
| // Replace this function if your board has multiple byte receive. | |||
| uint8_t receive(uint8_t* buf, size_t count) { | |||
| for (size_t i = 0; i < count; i++) { | |||
| buf[i] = SPI.transfer(0XFF); | |||
| } | |||
| return 0; | |||
| } | |||
| // Send a byte. | |||
| void send(uint8_t data) { | |||
| SPI.transfer(data); | |||
| } | |||
| // Send multiple bytes. | |||
| // Replace this function if your board has multiple byte send. | |||
| void send(const uint8_t* buf, size_t count) { | |||
| for (size_t i = 0; i < count; i++) { | |||
| SPI.transfer(buf[i]); | |||
| } | |||
| } | |||
| // Save SPISettings for new max SCK frequency | |||
| void setSckSpeed(uint32_t maxSck) { | |||
| m_spiSettings = SPISettings(maxSck, MSBFIRST, SPI_MODE0); | |||
| } | |||
| private: | |||
| SPISettings m_spiSettings; | |||
| } mySpi; | |||
| #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(50), &mySpi) | |||
| SdFat sd; | |||
| //------------------------------------------------------------------------------ | |||
| void setup() { | |||
| Serial.begin(9600); | |||
| if (!sd.begin(SD_CONFIG)) { | |||
| sd.initErrorHalt(&Serial); | |||
| } | |||
| sd.ls(&Serial, LS_SIZE); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void loop() {} | |||
| #else // SPI_DRIVER_SELECT | |||
| #error SPI_DRIVER_SELECT must be three in SdFat/SdFatConfig.h | |||
| #endif // SPI_DRIVER_SELECT | |||
| @@ -109,7 +109,7 @@ void setup() { | |||
| delay(200); // Catch Due reset problem | |||
| // initialize the SD card at SPI_FULL_SPEED for best performance. | |||
| // try SPI_HALF_SPEED if bus errors occur. | |||
| // try lower speed if bus errors occur. | |||
| if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) { | |||
| sd.initErrorHalt(&Serial); | |||
| } | |||
| @@ -62,7 +62,7 @@ void setup() { | |||
| delay(200); // Catch Due reset problem | |||
| // initialize the SD card at SPI_FULL_SPEED for best performance. | |||
| // try SPI_HALF_SPEED if bus errors occur. | |||
| // try lower speed if bus errors occur. | |||
| if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) { | |||
| sd.initErrorHalt(&Serial); | |||
| } | |||
| @@ -1,47 +1,50 @@ | |||
| 2017-08-10 | |||
| 2019-12-10 | |||
| Run the SdErrorCode example to produce an updated list. | |||
| C | |||
| Code,Symbol - failed operation | |||
| 0X0,SD_CARD_ERROR_NONE - No error | |||
| 0X1,SD_CARD_ERROR_CMD0 - Card reset failed | |||
| 0X2,SD_CARD_ERROR_CMD2 - SDIO read CID | |||
| 0X3,SD_CARD_ERROR_CMD3 - SDIO publish RCA | |||
| 0X4,SD_CARD_ERROR_CMD6 - Switch card function | |||
| 0X5,SD_CARD_ERROR_CMD7 - SDIO card select | |||
| 0X6,SD_CARD_ERROR_CMD8 - Send and check interface settings | |||
| 0X7,SD_CARD_ERROR_CMD9 - Read CSD data | |||
| 0X8,SD_CARD_ERROR_CMD10 - Read CID data | |||
| 0X9,SD_CARD_ERROR_CMD12 - Stop multiple block read | |||
| 0XA,SD_CARD_ERROR_CMD13 - Read card status | |||
| 0XB,SD_CARD_ERROR_CMD17 - Read single block | |||
| 0XC,SD_CARD_ERROR_CMD18 - Read multiple blocks | |||
| 0XD,SD_CARD_ERROR_CMD24 - Write single block | |||
| 0XE,SD_CARD_ERROR_CMD25 - Write multiple blocks | |||
| 0XF,SD_CARD_ERROR_CMD32 - Set first erase block | |||
| 0X00,SD_CARD_ERROR_NONE - No error | |||
| 0X01,SD_CARD_ERROR_CMD0 - Card reset failed | |||
| 0X02,SD_CARD_ERROR_CMD2 - SDIO read CID | |||
| 0X03,SD_CARD_ERROR_CMD3 - SDIO publish RCA | |||
| 0X04,SD_CARD_ERROR_CMD6 - Switch card function | |||
| 0X05,SD_CARD_ERROR_CMD7 - SDIO card select | |||
| 0X06,SD_CARD_ERROR_CMD8 - Send and check interface settings | |||
| 0X07,SD_CARD_ERROR_CMD9 - Read CSD data | |||
| 0X08,SD_CARD_ERROR_CMD10 - Read CID data | |||
| 0X09,SD_CARD_ERROR_CMD12 - Stop multiple block read | |||
| 0X0A,SD_CARD_ERROR_CMD13 - Read card status | |||
| 0X0B,SD_CARD_ERROR_CMD17 - Read single block | |||
| 0X0C,SD_CARD_ERROR_CMD18 - Read multiple blocks | |||
| 0X0D,SD_CARD_ERROR_CMD24 - Write single block | |||
| 0X0E,SD_CARD_ERROR_CMD25 - Write multiple blocks | |||
| 0X0F,SD_CARD_ERROR_CMD32 - Set first erase block | |||
| 0X10,SD_CARD_ERROR_CMD33 - Set last erase block | |||
| 0X11,SD_CARD_ERROR_CMD38 - Erase selected blocks | |||
| 0X12,SD_CARD_ERROR_CMD58 - Read OCR register | |||
| 0X13,SD_CARD_ERROR_CMD59 - Set CRC mode | |||
| 0X14,SD_CARD_ERROR_ACMD6 - Set SDIO bus width | |||
| 0X15,SD_CARD_ERROR_ACMD13 - Read extended status | |||
| 0X16,SD_CARD_ERROR_ACMD41 - Activate card initialization | |||
| 0X17,SD_CARD_ERROR_READ_TOKEN - Bad read data token | |||
| 0X18,SD_CARD_ERROR_READ_CRC - Read CRC error | |||
| 0X19,SD_CARD_ERROR_READ_FIFO - SDIO fifo read timeout | |||
| 0X1A,SD_CARD_ERROR_READ_REG - Read CID or CSD failed. | |||
| 0X1B,SD_CARD_ERROR_READ_START - Bad readStart argument | |||
| 0X1C,SD_CARD_ERROR_READ_TIMEOUT - Read data timeout | |||
| 0X1D,SD_CARD_ERROR_STOP_TRAN - Multiple block stop failed | |||
| 0X1E,SD_CARD_ERROR_WRITE_DATA - Write data not accepted | |||
| 0X1F,SD_CARD_ERROR_WRITE_FIFO - SDIO fifo write timeout | |||
| 0X20,SD_CARD_ERROR_WRITE_START - Bad writeStart argument | |||
| 0X21,SD_CARD_ERROR_WRITE_TIMEOUT - Flash programming timeout | |||
| 0X22,SD_CARD_ERROR_DMA - DMA transfer failed | |||
| 0X23,SD_CARD_ERROR_ERASE - Card did not accept erase commands | |||
| 0X24,SD_CARD_ERROR_ERASE_SINGLE_SECTOR - Card does not support erase | |||
| 0X25,SD_CARD_ERROR_ERASE_TIMEOUT - Erase command timeout | |||
| 0X26,SD_CARD_ERROR_INIT_NOT_CALLED - Card has not been initialized | |||
| 0X27,SD_CARD_ERROR_INVALID_CARD_CONFIG - Invalid card config | |||
| 0X28,SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED - Unsupported SDIO command | |||
| 0X29,SD_CARD_ERROR_UNKNOWN - Unknown error | |||
| 0X16,SD_CARD_ERROR_ACMD23 - Set pre-erased count | |||
| 0X17,SD_CARD_ERROR_ACMD41 - Activate card initialization | |||
| 0X18,SD_CARD_ERROR_READ_TOKEN - Bad read data token | |||
| 0X19,SD_CARD_ERROR_READ_CRC - Read CRC error | |||
| 0X1A,SD_CARD_ERROR_READ_FIFO - SDIO fifo read timeout | |||
| 0X1B,SD_CARD_ERROR_READ_REG - Read CID or CSD failed. | |||
| 0X1C,SD_CARD_ERROR_READ_START - Bad readStart argument | |||
| 0X1D,SD_CARD_ERROR_READ_TIMEOUT - Read data timeout | |||
| 0X1E,SD_CARD_ERROR_STOP_TRAN - Multiple block stop failed | |||
| 0X1F,SD_CARD_ERROR_WRITE_DATA - Write data not accepted | |||
| 0X20,SD_CARD_ERROR_WRITE_FIFO - SDIO fifo write timeout | |||
| 0X21,SD_CARD_ERROR_WRITE_START - Bad writeStart argument | |||
| 0X22,SD_CARD_ERROR_WRITE_PROGRAMMING - Flash programming | |||
| 0X23,SD_CARD_ERROR_WRITE_TIMEOUT - Write timeout | |||
| 0X24,SD_CARD_ERROR_DMA - DMA transfer failed | |||
| 0X25,SD_CARD_ERROR_ERASE - Card did not accept erase commands | |||
| 0X26,SD_CARD_ERROR_ERASE_SINGLE_SECTOR - Card does not support erase | |||
| 0X27,SD_CARD_ERROR_ERASE_TIMEOUT - Erase command timeout | |||
| 0X28,SD_CARD_ERROR_INIT_NOT_CALLED - Card has not been initialized | |||
| 0X29,SD_CARD_ERROR_INVALID_CARD_CONFIG - Invalid card config | |||
| 0X2A,SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED - Unsupported SDIO command | |||
| 0X2B,SD_CARD_ERROR_UNKNOWN - Unknown error | |||
| @@ -1,5 +1,5 @@ | |||
| name=SdFat | |||
| version=2.0.0-beta.7 | |||
| version=2.0.0-beta.8 | |||
| license=MIT | |||
| author=Bill Greiman <fat16lib@sbcglobal.net> | |||
| maintainer=Bill Greiman <fat16lib@sbcglobal.net> | |||
| @@ -508,6 +508,8 @@ size_t ExFatFile::printName(print_t* pr) { | |||
| DirName_t* dn; | |||
| DirPos_t pos = m_dirPos; | |||
| size_t n = 0; | |||
| uint8_t in; | |||
| uint8_t buf[15]; | |||
| if (!isOpen()) { | |||
| DBG_FAIL_MACRO; | |||
| goto fail; | |||
| @@ -523,16 +525,16 @@ size_t ExFatFile::printName(print_t* pr) { | |||
| DBG_FAIL_MACRO; | |||
| goto fail; | |||
| } | |||
| for (uint8_t in = 0; in < 15; in++) { | |||
| for (in = 0; in < 15; in++) { | |||
| uint16_t c = getLe16(dn->unicode + 2*in); | |||
| if (!c) { | |||
| goto done; | |||
| break;; | |||
| } | |||
| pr->write(c < 0X7f ? c : '?'); | |||
| buf[in] = c < 0X7f ? c : '?'; | |||
| n++; | |||
| } | |||
| pr->write(buf, in); | |||
| } | |||
| done: | |||
| return n; | |||
| fail: | |||
| @@ -506,9 +506,11 @@ fail: | |||
| //------------------------------------------------------------------------------ | |||
| size_t FatFile::printName(print_t* pr) { | |||
| FatFile dirFile; | |||
| uint16_t u; | |||
| size_t n = 0; | |||
| DirLfn_t* ldir; | |||
| size_t n = 0; | |||
| uint16_t u; | |||
| uint8_t buf[13]; | |||
| uint8_t i; | |||
| if (!isLFN()) { | |||
| return printSFN(pr); | |||
| @@ -532,24 +534,18 @@ size_t FatFile::printName(print_t* pr) { | |||
| DBG_FAIL_MACRO; | |||
| goto fail; | |||
| } | |||
| for (uint8_t i = 0; i < 13; i++) { | |||
| for (i = 0; i < 13; i++) { | |||
| u = lfnGetChar(ldir, i); | |||
| if (u == 0) { | |||
| // End of name. | |||
| break; | |||
| } | |||
| if (u > 0X7E) { | |||
| u = '?'; | |||
| } | |||
| pr->write(static_cast<char>(u)); | |||
| buf[i] = u < 0X7F ? u : '?'; | |||
| n++; | |||
| } | |||
| if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) { | |||
| return n; | |||
| } | |||
| pr->write(buf, i); | |||
| } | |||
| // Fall into fail; | |||
| DBG_FAIL_MACRO; | |||
| return n; | |||
| fail: | |||
| return 0; | |||
| @@ -25,7 +25,8 @@ | |||
| #include "FsLib.h" | |||
| //------------------------------------------------------------------------------ | |||
| FsBaseFile::FsBaseFile(const FsBaseFile& from) { | |||
| close(); | |||
| m_fFile = nullptr; | |||
| m_xFile = nullptr; | |||
| if (from.m_fFile) { | |||
| m_fFile = new (m_fileMem) FatFile; | |||
| *m_fFile = *from.m_fFile; | |||
| @@ -55,7 +55,7 @@ class SdCardFactory { | |||
| * \return generic card pointer. | |||
| */ | |||
| SdCard* newCard(SdSpiConfig config) { | |||
| m_spiCard.begin(&m_spi, config); | |||
| m_spiCard.begin(config); | |||
| return &m_spiCard; | |||
| } | |||
| /** Initialize SDIO card. | |||
| @@ -78,6 +78,5 @@ class SdCardFactory { | |||
| SdioCard m_sdioCard; | |||
| #endif // HAS_SDIO_CLASS | |||
| SdSpiCard m_spiCard; | |||
| SdSpiDriver m_spi; | |||
| }; | |||
| #endif // SdCard_h | |||
| @@ -220,16 +220,22 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) { | |||
| //============================================================================== | |||
| // SdSpiCard member functions | |||
| //------------------------------------------------------------------------------ | |||
| bool SdSpiCard::begin(SdSpiDriver* spi, SdSpiConfig spiConfig) { | |||
| bool SdSpiCard::begin(SdSpiConfig spiConfig) { | |||
| SdMillis_t t0 = SysCall::curTimeMS(); | |||
| m_errorCode = SD_CARD_ERROR_NONE; | |||
| m_type = 0; | |||
| m_csPin = spiConfig.csPin; | |||
| #if SPI_DRIVER_SELECT >= 2 | |||
| m_spiDriverPtr = spiConfig.spiPort; | |||
| if (!m_spiDriverPtr) { | |||
| error(SD_CARD_ERROR_INVALID_CARD_CONFIG); | |||
| goto fail; | |||
| } | |||
| #endif // SPI_DRIVER_SELECT | |||
| sdCsInit(m_csPin); | |||
| spiUnselect(); | |||
| m_spiDriver = spi; | |||
| m_spiDriver->setSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ); | |||
| m_spiDriver->begin(spiConfig); | |||
| SdMillis_t t0 = SysCall::curTimeMS(); | |||
| spiSetSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ); | |||
| spiBegin(spiConfig); | |||
| uint32_t arg; | |||
| #if ENABLE_DEDICATED_SPI | |||
| m_sharedSpi = !(spiConfig.options & DEDICATED_SPI); | |||
| @@ -317,7 +323,7 @@ bool SdSpiCard::begin(SdSpiDriver* spi, SdSpiConfig spiConfig) { | |||
| } | |||
| } | |||
| spiStop(); | |||
| m_spiDriver->setSckSpeed(spiConfig.maxSck); | |||
| spiSetSckSpeed(spiConfig.maxSck); | |||
| return true; | |||
| fail: | |||
| @@ -53,7 +53,7 @@ class SdSpiCard { | |||
| * \param[in] spiConfig SPI card configuration. | |||
| * \return true for success or false for failure. | |||
| */ | |||
| bool begin(SdSpiDriver* spi, SdSpiConfig spiConfig); | |||
| bool begin(SdSpiConfig spiConfig); | |||
| /** Clear debug stats. */ | |||
| void dbgClearStats(); | |||
| /** Print debug stats. */ | |||
| @@ -285,40 +285,71 @@ class SdSpiCard { | |||
| bool isTimedOut(SdMillis_t startMS, SdMillis_t timeoutMS); | |||
| bool readData(uint8_t* dst, size_t count); | |||
| bool readRegister(uint8_t cmd, void* buf); | |||
| void spiSelect() { | |||
| sdCsWrite(m_csPin, false); | |||
| } | |||
| void type(uint8_t value) { | |||
| m_type = value; | |||
| } | |||
| void spiUnselect() { | |||
| sdCsWrite(m_csPin, true); | |||
| } | |||
| bool waitNotBusy(SdMillis_t timeoutMS); | |||
| bool writeData(uint8_t token, const uint8_t* src); | |||
| //--------------------------------------------------------------------------- | |||
| // functions defined in SdSpiDriver.h | |||
| #if SPI_DRIVER_SELECT < 2 | |||
| void spiActivate() { | |||
| m_spiDriver->activate(); | |||
| m_spiDriver.activate(); | |||
| } | |||
| void spiBegin(SdSpiConfig spiConfig) { | |||
| m_spiDriver.begin(spiConfig); | |||
| } | |||
| void spiDeactivate() { | |||
| m_spiDriver->deactivate(); | |||
| m_spiDriver.deactivate(); | |||
| } | |||
| uint8_t spiReceive() { | |||
| return m_spiDriver->receive(); | |||
| return m_spiDriver.receive(); | |||
| } | |||
| uint8_t spiReceive(uint8_t* buf, size_t n) { | |||
| return m_spiDriver->receive(buf, n); | |||
| return m_spiDriver.receive(buf, n); | |||
| } | |||
| void spiSend(uint8_t data) { | |||
| m_spiDriver->send(data); | |||
| m_spiDriver.send(data); | |||
| } | |||
| void spiSend(const uint8_t* buf, size_t n) { | |||
| m_spiDriver->send(buf, n); | |||
| m_spiDriver.send(buf, n); | |||
| } | |||
| void spiSelect() { | |||
| sdCsWrite(m_csPin, false); | |||
| void spiSetSckSpeed(uint32_t maxSck) { | |||
| m_spiDriver.setSckSpeed(maxSck); | |||
| } | |||
| void spiUnselect() { | |||
| sdCsWrite(m_csPin, true); | |||
| SdSpiDriver m_spiDriver; | |||
| #else // SPI_DRIVER_SELECT < 2 | |||
| void spiActivate() { | |||
| m_spiDriverPtr->activate(); | |||
| } | |||
| void spiBegin(SdSpiConfig spiConfig) { | |||
| m_spiDriverPtr->begin(spiConfig); | |||
| } | |||
| void spiDeactivate() { | |||
| m_spiDriverPtr->deactivate(); | |||
| } | |||
| uint8_t spiReceive() { | |||
| return m_spiDriverPtr->receive(); | |||
| } | |||
| uint8_t spiReceive(uint8_t* buf, size_t n) { | |||
| return m_spiDriverPtr->receive(buf, n); | |||
| } | |||
| void spiSend(uint8_t data) { | |||
| m_spiDriverPtr->send(data); | |||
| } | |||
| void spiSend(const uint8_t* buf, size_t n) { | |||
| m_spiDriverPtr->send(buf, n); | |||
| } | |||
| void spiSetSckSpeed(uint32_t maxSck) { | |||
| m_spiDriverPtr->setSckSpeed(maxSck); | |||
| } | |||
| SdSpiDriver* m_spiDriverPtr; | |||
| #endif // SPI_DRIVER_SELECT < 2 | |||
| #if ENABLE_DEDICATED_SPI | |||
| static const uint8_t IDLE_STATE = 0; | |||
| static const uint8_t READ_STATE = 1; | |||
| @@ -327,7 +358,6 @@ class SdSpiCard { | |||
| uint8_t m_curState; | |||
| bool m_sharedSpi; | |||
| #endif // ENABLE_DEDICATED_SPI | |||
| SdSpiDriver *m_spiDriver; | |||
| SdCsPin_t m_csPin; | |||
| uint8_t m_errorCode; | |||
| bool m_spiActive; | |||
| @@ -38,13 +38,13 @@ | |||
| #define ENABLE_ARDUINO_SERIAL 1 | |||
| /** For Debug - must be one */ | |||
| #define ENABLE_ARDUINO_STRING 1 | |||
| /** Set USE_BLOCK_DEVICE_INTERFACE nonzero to use generic of block device */ | |||
| /** Set USE_BLOCK_DEVICE_INTERFACE nonzero to use generic block device */ | |||
| #define USE_BLOCK_DEVICE_INTERFACE 0 | |||
| //------------------------------------------------------------------------------ | |||
| #if ENABLE_ARDUINO_FEATURES | |||
| #include "Arduino.h" | |||
| #ifdef PLATFORM_ID | |||
| // Only defined if a Particle device | |||
| // Only defined if a Particle device. | |||
| #include "application.h" | |||
| #endif // PLATFORM_ID | |||
| #endif // ENABLE_ARDUINO_FEATURES | |||
| @@ -56,8 +56,8 @@ | |||
| #define INCLUDE_SDIOS 0 | |||
| //------------------------------------------------------------------------------ | |||
| /** | |||
| * Optimize access to contiguous files. | |||
| * Experimental - set nonzero to enable. | |||
| * Set USE_FAT_FILE_FLAG_CONTIGUOUS nonzero to optimize access to | |||
| * contiguous files. | |||
| */ | |||
| #define USE_FAT_FILE_FLAG_CONTIGUOUS 1 | |||
| //------------------------------------------------------------------------------ | |||
| @@ -101,9 +101,9 @@ | |||
| * | |||
| * 1 - The standard library driver is always used. | |||
| * | |||
| * 2 - The software SPI driver is always used. | |||
| * 2 - An external SPI driver of SoftSpiDriver template class is always used. | |||
| * | |||
| * 3 - Experimental external SPI driver hook. | |||
| * 3 - An external SPI driver derived from SdSpiBaseClass is always used. | |||
| */ | |||
| #define SPI_DRIVER_SELECT 0 | |||
| //------------------------------------------------------------------------------ | |||
| @@ -56,7 +56,12 @@ void SdSpiArduinoDriver::send(uint8_t data) { | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void SdSpiArduinoDriver::send(const uint8_t *buf, size_t count) { | |||
| // Convert byte array to 4 byte array | |||
| // If not a multiple of four. Command with CRC used six byte send. | |||
| while (count%4) { | |||
| send(*buf++); | |||
| count--; | |||
| } | |||
| // Convert byte array to 4 byte array. | |||
| uint32_t myArray[count/4]; // NOLINT | |||
| for (int x = 0; x < count/4; x++) { | |||
| myArray[x] = ((uint32_t)buf[(x * 4) + 3] << (8 * 3)) | | |||
| @@ -37,7 +37,7 @@ class SdSpiBaseClass { | |||
| /** Activate SPI hardware. */ | |||
| virtual void activate() {} | |||
| /** Initialize the SPI bus. */ | |||
| virtual void begin() = 0; | |||
| virtual void begin(SdSpiConfig config) = 0; | |||
| /** Deactivate SPI hardware. */ | |||
| virtual void deactivate() {} | |||
| /** Receive a byte. | |||
| @@ -70,63 +70,4 @@ class SdSpiBaseClass { | |||
| */ | |||
| virtual void setSckSpeed(uint32_t maxSck) {(void)maxSck;} | |||
| }; | |||
| #include "SPI.h" | |||
| /** | |||
| * \class MySpiClass | |||
| * \brief Sample external SPI class. | |||
| */ | |||
| class MySpiClass : public SdSpiBaseClass { | |||
| public: | |||
| /** Activate SPI hardware. */ | |||
| void activate() { | |||
| SPI.beginTransaction(m_spiSettings); | |||
| } | |||
| /** Initialize the SPI bus. */ | |||
| void begin() {SPI.begin();} | |||
| /** Deactivate SPI hardware. */ | |||
| void deactivate() {SPI.endTransaction();} | |||
| /** 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] count Number of bytes to receive. | |||
| * | |||
| * \return Zero for no error or nonzero error code. | |||
| */ | |||
| uint8_t receive(uint8_t* buf, size_t count) { | |||
| for (size_t i = 0; i < count; i++) { | |||
| buf[i] = SPI.transfer(0XFF); | |||
| } | |||
| return 0; | |||
| } | |||
| /** Send a byte. | |||
| * | |||
| * \param[in] data Byte to send | |||
| */ | |||
| void send(uint8_t data) {SPI.transfer(data);} | |||
| /** Send multiple bytes. | |||
| * | |||
| * \param[in] buf Buffer for data to be sent. | |||
| * \param[in] count Number of bytes to send. | |||
| */ | |||
| void send(const uint8_t* buf, size_t count) { | |||
| for (size_t i = 0; i < count; i++) { | |||
| SPI.transfer(buf[i]); | |||
| } | |||
| } | |||
| /** Save high speed SPISettings after SD initialization. | |||
| * | |||
| * \param[in] maxSck Maximum SCK frequency. | |||
| */ | |||
| void setSckSpeed(uint32_t maxSck) { | |||
| m_spiSettings = SPISettings(maxSck, MSBFIRST, SPI_MODE0); | |||
| } | |||
| private: | |||
| SPISettings m_spiSettings; | |||
| }; | |||
| #endif // SdSpiBaseClass_h | |||
| @@ -33,8 +33,8 @@ void sdCsInit(SdCsPin_t pin) { | |||
| void sdCsWrite(SdCsPin_t pin, bool level) { | |||
| digitalWrite(pin, level); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| #elif SD_CHIP_SELECT_MODE == 1 | |||
| //------------------------------------------------------------------------------ | |||
| __attribute__((weak)) | |||
| void sdCsInit(SdCsPin_t pin) { | |||
| pinMode(pin, OUTPUT); | |||
| @@ -47,21 +47,21 @@ void sdCsWrite(SdCsPin_t pin, bool level); | |||
| #define SD_SCK_HZ(maxSpeed) (maxSpeed) | |||
| /** SPISettings for SCK frequency in MHz. */ | |||
| #define SD_SCK_MHZ(maxMhz) (1000000UL*(maxMhz)) | |||
| // SPI divisor constants | |||
| // SPI divisor constants - obsolete. | |||
| /** Set SCK to max 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) | |||
| /** Set SCK rate to F_CPU/6 for Due */ | |||
| #define SPI_DIV6_SPEED SD_SCK_HZ(F_CPU/6) | |||
| /** Set SCK rate to F_CPU/8. */ | |||
| #define SPI_QUARTER_SPEED SD_SCK_HZ(F_CPU/8) | |||
| /** Set SCK rate to F_CPU/16. */ | |||
| #define SPI_EIGHTH_SPEED SD_SCK_HZ(F_CPU/16) | |||
| /** Set SCK rate to F_CPU/32. */ | |||
| #define SPI_SIXTEENTH_SPEED SD_SCK_HZ(F_CPU/32) | |||
| /** Set SCK rate to 16 MHz for Due */ | |||
| #define SPI_DIV3_SPEED SD_SCK_MHZ(16) | |||
| /** Set SCK rate to 4 MHz for AVR. */ | |||
| #define SPI_HALF_SPEED SD_SCK_MHZ(4) | |||
| /** Set SCK rate to 8 MHz for Due */ | |||
| #define SPI_DIV6_SPEED SD_SCK_MHZ(8) | |||
| /** Set SCK rate to 2 MHz for AVR. */ | |||
| #define SPI_QUARTER_SPEED SD_SCK_MHZ(2) | |||
| /** Set SCK rate to 1 MHz for AVR. */ | |||
| #define SPI_EIGHTH_SPEED SD_SCK_MHZ(1) | |||
| /** Set SCK rate to 500 kHz for AVR. */ | |||
| #define SPI_SIXTEENTH_SPEED SD_SCK_HZ(500000) | |||
| //------------------------------------------------------------------------------ | |||
| /** The SD is the only device on the SPI bus. */ | |||
| #define DEDICATED_SPI 0X80 | |||
| @@ -69,15 +69,18 @@ void sdCsWrite(SdCsPin_t pin, bool level); | |||
| #define SHARED_SPI 0 | |||
| #if SPI_DRIVER_SELECT < 2 | |||
| #include "SPI.h" | |||
| /** Port type for SPI hardware driver. */ | |||
| /** Port type for Arduino SPI hardware driver. */ | |||
| typedef SPIClass SpiPort_t; | |||
| #elif SPI_DRIVER_SELECT == 2 | |||
| class SoftSPIClass; | |||
| class SdSpiSoftDriver; | |||
| /** Port type for software SPI driver. */ | |||
| typedef SoftSPIClass SpiPort_t; | |||
| #else // SPI_DRIVER_SELECT | |||
| #include "SdSpiBaseClass.h" | |||
| typedef SdSpiSoftDriver SpiPort_t; | |||
| #elif SPI_DRIVER_SELECT == 3 | |||
| class SdSpiBaseClass; | |||
| /** Port type for extrernal SPI driver. */ | |||
| typedef SdSpiBaseClass SpiPort_t; | |||
| #else // SPI_DRIVER_SELECT | |||
| typedef void* SpiPort_t; | |||
| #endif // SPI_DRIVER_SELECT | |||
| //------------------------------------------------------------------------------ | |||
| /** | |||
| @@ -110,13 +113,13 @@ class SdSpiConfig { | |||
| * \param[in] opt Options. | |||
| */ | |||
| SdSpiConfig(SdCsPin_t cs, uint8_t opt) : | |||
| csPin(cs), options(opt), maxSck(SPI_FULL_SPEED), spiPort(nullptr) {} | |||
| csPin(cs), options(opt), maxSck(SD_SCK_MHZ(50)), spiPort(nullptr) {} | |||
| /** SdSpiConfig constructor. | |||
| * | |||
| * \param[in] cs Chip select pin. | |||
| */ | |||
| explicit SdSpiConfig(SdCsPin_t cs) : csPin(cs), options(SHARED_SPI), | |||
| maxSck(SPI_FULL_SPEED), spiPort(nullptr) {} | |||
| maxSck(SD_SCK_MHZ(50)), spiPort(nullptr) {} | |||
| /** Chip select pin. */ | |||
| const SdCsPin_t csPin; | |||
| @@ -127,16 +130,13 @@ class SdSpiConfig { | |||
| /** SPI port */ | |||
| SpiPort_t* spiPort; | |||
| }; | |||
| #if SPI_DRIVER_SELECT < 2 | |||
| #include "SdSpiArduinoDriver.h" | |||
| #elif SPI_DRIVER_SELECT == 2 | |||
| #include "SdSpiSoftDriver.h" | |||
| #elif SPI_DRIVER_SELECT == 3 | |||
| #include "SdSpiExternalDriver.h" | |||
| #elif SPI_DRIVER_SELECT == 4 | |||
| #include "SdSpiBareUnoDriver.h" | |||
| typedef SdSpiDriverBareUno SdSpiDriver; | |||
| #include "SdSpiBaseClass.h" | |||
| typedef SdSpiBaseClass SdSpiDriver; | |||
| #else // SPI_DRIVER_SELECT | |||
| #error Invalid SPI_DRIVER_SELECT | |||
| #endif // SPI_DRIVER_SELECT | |||
| @@ -1,90 +0,0 @@ | |||
| /** | |||
| * Copyright (c) 2011-2019 Bill Greiman | |||
| * This file is part of the SdFat library for SD memory cards. | |||
| * | |||
| * MIT License | |||
| * | |||
| * Permission is hereby granted, free of charge, to any person obtaining a | |||
| * copy of this software and associated documentation files (the "Software"), | |||
| * to deal in the Software without restriction, including without limitation | |||
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| * and/or sell copies of the Software, and to permit persons to whom the | |||
| * Software is furnished to do so, subject to the following conditions: | |||
| * | |||
| * The above copyright notice and this permission notice shall be included | |||
| * in all copies or substantial portions of the Software. | |||
| * | |||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| * DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /** | |||
| * \file | |||
| * \brief Class for external drivers. | |||
| */ | |||
| #ifndef SdSpiExternalDriver_h | |||
| #define SdSpiExternalDriver_h | |||
| /** | |||
| * \class SdExternalSpiDriver | |||
| * \brief Class for external SPI. | |||
| */ | |||
| class SdExternalSpiDriver { | |||
| public: | |||
| /** Activate SPI hardware. */ | |||
| void activate() {if (m_spi) m_spi->activate();} | |||
| /** Initialize the SPI bus. | |||
| * | |||
| * \param[in] spiConfig SD card configuration. | |||
| */ | |||
| void begin(SdSpiConfig spiConfig) { | |||
| m_spi = spiConfig.spiPort; | |||
| if (m_spi) m_spi->begin(); | |||
| } | |||
| /** Deactivate SPI hardware. */ | |||
| void deactivate() {if (m_spi) m_spi->deactivate();} | |||
| /** Receive a byte. | |||
| * | |||
| * \return The byte. | |||
| */ | |||
| uint8_t receive() {return m_spi ? m_spi->receive(): 0XFF;} | |||
| /** Receive multiple bytes. | |||
| * | |||
| * \param[out] buf Buffer to receive the data. | |||
| * \param[in] count Number of bytes to receive. | |||
| * | |||
| * \return Zero for no error or nonzero error code. | |||
| */ | |||
| uint8_t receive(uint8_t* buf, size_t count) { | |||
| return m_spi ? m_spi->receive(buf, count) : 1; | |||
| } | |||
| /** Send a byte. | |||
| * | |||
| * \param[in] data Byte to send | |||
| */ | |||
| void send(uint8_t data) {if (m_spi) m_spi->send(data);} | |||
| /** Send multiple bytes. | |||
| * | |||
| * \param[in] buf Buffer for data to be sent. | |||
| * \param[in] count Number of bytes to send. | |||
| */ | |||
| void send(const uint8_t* buf, size_t count) { | |||
| if (m_spi) m_spi->send(buf, count); | |||
| } | |||
| /** Save high speed SPISettings after SD initialization. | |||
| * | |||
| * \param[in] maxSck Maximum SCK frequency. | |||
| */ | |||
| void setSckSpeed(uint32_t maxSck) { | |||
| if (m_spi) m_spi->setSckSpeed(maxSck); | |||
| } | |||
| private: | |||
| SdSpiBaseClass* m_spi; | |||
| }; | |||
| /** Typedef for use of SdExternalSpiDriver */ | |||
| typedef SdExternalSpiDriver SdSpiDriver; | |||
| #endif // SdSpiExternalDriver_h | |||
| @@ -30,64 +30,22 @@ | |||
| #define SdSpiSoftDriver_h | |||
| #include "../DigitalIO/SoftSPI.h" | |||
| /** | |||
| * \class SoftSPIClass | |||
| * \class SdSpiSoftDriver | |||
| * \brief Base class for external soft SPI. | |||
| */ | |||
| class SoftSPIClass { | |||
| public: | |||
| /** Initialize the SPI bus. */ | |||
| virtual void begin() = 0; | |||
| /** Receive a byte. | |||
| * | |||
| * \return The byte. | |||
| */ | |||
| virtual uint8_t receive() = 0; | |||
| /** Send a byte. | |||
| * | |||
| * \param[in] data Byte to send | |||
| */ | |||
| virtual void send(uint8_t data) = 0; | |||
| }; | |||
| //------------------------------------------------------------------------------ | |||
| /** | |||
| * \class SoftSpiDriver | |||
| * \brief Class for external soft SPI. | |||
| */ | |||
| template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin> | |||
| class SoftSpiDriver : public SoftSPIClass { | |||
| public: | |||
| /** Initialize the SPI bus. */ | |||
| void begin() {m_spi.begin();} | |||
| /** Receive a byte. | |||
| * | |||
| * \return The byte. | |||
| */ | |||
| uint8_t receive() {return m_spi.receive();} | |||
| /** Send a byte. | |||
| * | |||
| * \param[in] data Byte to send | |||
| */ | |||
| void send(uint8_t data) {m_spi.send(data);} | |||
| private: | |||
| SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi; | |||
| }; | |||
| //------------------------------------------------------------------------------ | |||
| /** | |||
| * \class SdSoftSpiDriver | |||
| * \brief Class for SdSoftSpiDriver. | |||
| */ | |||
| class SdSoftSpiDriver { | |||
| class SdSpiSoftDriver { | |||
| public: | |||
| /** Activate SPI hardware. */ | |||
| void activate() {} | |||
| /** Initialize the SPI bus. */ | |||
| virtual void begin() = 0; | |||
| /** Initialize the SPI bus. | |||
| * | |||
| * \param[in] spiConfig SD card configuration. | |||
| */ | |||
| void begin(SdSpiConfig spiConfig) { | |||
| m_spi = spiConfig.spiPort; | |||
| if (m_spi) m_spi->begin(); | |||
| (void)spiConfig; | |||
| begin(); | |||
| } | |||
| /** Deactivate SPI hardware. */ | |||
| void deactivate() {} | |||
| @@ -95,14 +53,14 @@ class SdSoftSpiDriver { | |||
| * | |||
| * \return The byte. | |||
| */ | |||
| uint8_t receive() {return m_spi ? m_spi->receive() : 0XFF;} | |||
| virtual uint8_t receive() = 0; | |||
| /** Receive multiple bytes. | |||
| * | |||
| * \param[out] buf Buffer to receive the data. | |||
| * \param[in] count Number of bytes to receive. | |||
| * | |||
| * \return Zero for no error or nonzero error code. | |||
| */ | |||
| * | |||
| * \param[out] buf Buffer to receive the data. | |||
| * \param[in] count Number of bytes to receive. | |||
| * | |||
| * \return Zero for no error or nonzero error code. | |||
| */ | |||
| uint8_t receive(uint8_t* buf, size_t count) { | |||
| for (size_t i = 0; i < count; i++) { | |||
| buf[i] = receive(); | |||
| @@ -113,7 +71,7 @@ class SdSoftSpiDriver { | |||
| * | |||
| * \param[in] data Byte to send | |||
| */ | |||
| void send(uint8_t data) {if (m_spi) m_spi->send(data);} | |||
| virtual void send(uint8_t data) = 0; | |||
| /** Send multiple bytes. | |||
| * | |||
| * \param[in] buf Buffer for data to be sent. | |||
| @@ -131,10 +89,31 @@ class SdSoftSpiDriver { | |||
| void setSckSpeed(uint32_t maxSck) { | |||
| (void)maxSck; | |||
| } | |||
| }; | |||
| //------------------------------------------------------------------------------ | |||
| /** | |||
| * \class SoftSpiDriver | |||
| * \brief Class for external soft SPI. | |||
| */ | |||
| template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin> | |||
| class SoftSpiDriver : public SdSpiSoftDriver { | |||
| public: | |||
| /** Initialize the SPI bus. */ | |||
| void begin() {m_spi.begin();} | |||
| /** Receive a byte. | |||
| * | |||
| * \return The byte. | |||
| */ | |||
| uint8_t receive() {return m_spi.receive();} | |||
| /** Send a byte. | |||
| * | |||
| * \param[in] data Byte to send | |||
| */ | |||
| void send(uint8_t data) {m_spi.send(data);} | |||
| private: | |||
| SoftSPIClass* m_spi; | |||
| SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi; | |||
| }; | |||
| /** Typedef for use of SdSoftSpiDriver */ | |||
| typedef SdSoftSpiDriver SdSpiDriver; | |||
| typedef SdSpiSoftDriver SdSpiDriver; | |||
| #endif // SdSpiSoftDriver_h | |||