| const uint8_t SD_CS_PIN = SDCARD_SS_PIN; | const uint8_t SD_CS_PIN = SDCARD_SS_PIN; | ||||
| #endif // 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) | #define SD_CONFIG SdSpiConfig(SD_CS_PIN) | ||||
| SdExFat sd; | SdExFat sd; |
| // 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 |
| // 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 |
| delay(200); // Catch Due reset problem | delay(200); // Catch Due reset problem | ||||
| // initialize the SD card at SPI_FULL_SPEED for best performance. | // initialize the SD card at SPI_FULL_SPEED for best performance. | ||||
| // try SPI_HALF_SPEED if bus errors occur. | |||||
| // try lower speed if bus errors occur. | |||||
| if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) { | if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) { | ||||
| sd.initErrorHalt(&Serial); | sd.initErrorHalt(&Serial); | ||||
| } | } |
| delay(200); // Catch Due reset problem | delay(200); // Catch Due reset problem | ||||
| // initialize the SD card at SPI_FULL_SPEED for best performance. | // initialize the SD card at SPI_FULL_SPEED for best performance. | ||||
| // try SPI_HALF_SPEED if bus errors occur. | |||||
| // try lower speed if bus errors occur. | |||||
| if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) { | if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) { | ||||
| sd.initErrorHalt(&Serial); | sd.initErrorHalt(&Serial); | ||||
| } | } |
| 2017-08-10 | |||||
| 2019-12-10 | |||||
| Run the SdErrorCode example to produce an updated list. | Run the SdErrorCode example to produce an updated list. | ||||
| C | |||||
| Code,Symbol - failed operation | 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 | 0X10,SD_CARD_ERROR_CMD33 - Set last erase block | ||||
| 0X11,SD_CARD_ERROR_CMD38 - Erase selected blocks | 0X11,SD_CARD_ERROR_CMD38 - Erase selected blocks | ||||
| 0X12,SD_CARD_ERROR_CMD58 - Read OCR register | 0X12,SD_CARD_ERROR_CMD58 - Read OCR register | ||||
| 0X13,SD_CARD_ERROR_CMD59 - Set CRC mode | 0X13,SD_CARD_ERROR_CMD59 - Set CRC mode | ||||
| 0X14,SD_CARD_ERROR_ACMD6 - Set SDIO bus width | 0X14,SD_CARD_ERROR_ACMD6 - Set SDIO bus width | ||||
| 0X15,SD_CARD_ERROR_ACMD13 - Read extended status | 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 |
| name=SdFat | name=SdFat | ||||
| version=2.0.0-beta.7 | |||||
| version=2.0.0-beta.8 | |||||
| license=MIT | license=MIT | ||||
| author=Bill Greiman <fat16lib@sbcglobal.net> | author=Bill Greiman <fat16lib@sbcglobal.net> | ||||
| maintainer=Bill Greiman <fat16lib@sbcglobal.net> | maintainer=Bill Greiman <fat16lib@sbcglobal.net> |
| DirName_t* dn; | DirName_t* dn; | ||||
| DirPos_t pos = m_dirPos; | DirPos_t pos = m_dirPos; | ||||
| size_t n = 0; | size_t n = 0; | ||||
| uint8_t in; | |||||
| uint8_t buf[15]; | |||||
| if (!isOpen()) { | if (!isOpen()) { | ||||
| DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
| goto fail; | goto fail; | ||||
| DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
| goto fail; | goto fail; | ||||
| } | } | ||||
| for (uint8_t in = 0; in < 15; in++) { | |||||
| for (in = 0; in < 15; in++) { | |||||
| uint16_t c = getLe16(dn->unicode + 2*in); | uint16_t c = getLe16(dn->unicode + 2*in); | ||||
| if (!c) { | if (!c) { | ||||
| goto done; | |||||
| break;; | |||||
| } | } | ||||
| pr->write(c < 0X7f ? c : '?'); | |||||
| buf[in] = c < 0X7f ? c : '?'; | |||||
| n++; | n++; | ||||
| } | } | ||||
| pr->write(buf, in); | |||||
| } | } | ||||
| done: | |||||
| return n; | return n; | ||||
| fail: | fail: |
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| size_t FatFile::printName(print_t* pr) { | size_t FatFile::printName(print_t* pr) { | ||||
| FatFile dirFile; | FatFile dirFile; | ||||
| uint16_t u; | |||||
| size_t n = 0; | |||||
| DirLfn_t* ldir; | DirLfn_t* ldir; | ||||
| size_t n = 0; | |||||
| uint16_t u; | |||||
| uint8_t buf[13]; | |||||
| uint8_t i; | |||||
| if (!isLFN()) { | if (!isLFN()) { | ||||
| return printSFN(pr); | return printSFN(pr); | ||||
| DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
| goto fail; | goto fail; | ||||
| } | } | ||||
| for (uint8_t i = 0; i < 13; i++) { | |||||
| for (i = 0; i < 13; i++) { | |||||
| u = lfnGetChar(ldir, i); | u = lfnGetChar(ldir, i); | ||||
| if (u == 0) { | if (u == 0) { | ||||
| // End of name. | // End of name. | ||||
| break; | break; | ||||
| } | } | ||||
| if (u > 0X7E) { | |||||
| u = '?'; | |||||
| } | |||||
| pr->write(static_cast<char>(u)); | |||||
| buf[i] = u < 0X7F ? u : '?'; | |||||
| n++; | n++; | ||||
| } | } | ||||
| if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) { | |||||
| return n; | |||||
| } | |||||
| pr->write(buf, i); | |||||
| } | } | ||||
| // Fall into fail; | |||||
| DBG_FAIL_MACRO; | |||||
| return n; | |||||
| fail: | fail: | ||||
| return 0; | return 0; |
| #include "FsLib.h" | #include "FsLib.h" | ||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| FsBaseFile::FsBaseFile(const FsBaseFile& from) { | FsBaseFile::FsBaseFile(const FsBaseFile& from) { | ||||
| close(); | |||||
| m_fFile = nullptr; | |||||
| m_xFile = nullptr; | |||||
| if (from.m_fFile) { | if (from.m_fFile) { | ||||
| m_fFile = new (m_fileMem) FatFile; | m_fFile = new (m_fileMem) FatFile; | ||||
| *m_fFile = *from.m_fFile; | *m_fFile = *from.m_fFile; |
| * \return generic card pointer. | * \return generic card pointer. | ||||
| */ | */ | ||||
| SdCard* newCard(SdSpiConfig config) { | SdCard* newCard(SdSpiConfig config) { | ||||
| m_spiCard.begin(&m_spi, config); | |||||
| m_spiCard.begin(config); | |||||
| return &m_spiCard; | return &m_spiCard; | ||||
| } | } | ||||
| /** Initialize SDIO card. | /** Initialize SDIO card. | ||||
| SdioCard m_sdioCard; | SdioCard m_sdioCard; | ||||
| #endif // HAS_SDIO_CLASS | #endif // HAS_SDIO_CLASS | ||||
| SdSpiCard m_spiCard; | SdSpiCard m_spiCard; | ||||
| SdSpiDriver m_spi; | |||||
| }; | }; | ||||
| #endif // SdCard_h | #endif // SdCard_h |
| //============================================================================== | //============================================================================== | ||||
| // SdSpiCard member functions | // 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_errorCode = SD_CARD_ERROR_NONE; | ||||
| m_type = 0; | m_type = 0; | ||||
| m_csPin = spiConfig.csPin; | 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); | sdCsInit(m_csPin); | ||||
| spiUnselect(); | 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; | uint32_t arg; | ||||
| #if ENABLE_DEDICATED_SPI | #if ENABLE_DEDICATED_SPI | ||||
| m_sharedSpi = !(spiConfig.options & DEDICATED_SPI); | m_sharedSpi = !(spiConfig.options & DEDICATED_SPI); | ||||
| } | } | ||||
| } | } | ||||
| spiStop(); | spiStop(); | ||||
| m_spiDriver->setSckSpeed(spiConfig.maxSck); | |||||
| spiSetSckSpeed(spiConfig.maxSck); | |||||
| return true; | return true; | ||||
| fail: | fail: |
| * \param[in] spiConfig SPI card configuration. | * \param[in] spiConfig SPI card configuration. | ||||
| * \return true for success or false for failure. | * \return true for success or false for failure. | ||||
| */ | */ | ||||
| bool begin(SdSpiDriver* spi, SdSpiConfig spiConfig); | |||||
| bool begin(SdSpiConfig spiConfig); | |||||
| /** Clear debug stats. */ | /** Clear debug stats. */ | ||||
| void dbgClearStats(); | void dbgClearStats(); | ||||
| /** Print debug stats. */ | /** Print debug stats. */ | ||||
| bool isTimedOut(SdMillis_t startMS, SdMillis_t timeoutMS); | bool isTimedOut(SdMillis_t startMS, SdMillis_t timeoutMS); | ||||
| bool readData(uint8_t* dst, size_t count); | bool readData(uint8_t* dst, size_t count); | ||||
| bool readRegister(uint8_t cmd, void* buf); | bool readRegister(uint8_t cmd, void* buf); | ||||
| void spiSelect() { | |||||
| sdCsWrite(m_csPin, false); | |||||
| } | |||||
| void type(uint8_t value) { | void type(uint8_t value) { | ||||
| m_type = value; | m_type = value; | ||||
| } | } | ||||
| void spiUnselect() { | |||||
| sdCsWrite(m_csPin, true); | |||||
| } | |||||
| bool waitNotBusy(SdMillis_t timeoutMS); | bool waitNotBusy(SdMillis_t timeoutMS); | ||||
| bool writeData(uint8_t token, const uint8_t* src); | bool writeData(uint8_t token, const uint8_t* src); | ||||
| //--------------------------------------------------------------------------- | |||||
| // functions defined in SdSpiDriver.h | |||||
| #if SPI_DRIVER_SELECT < 2 | |||||
| void spiActivate() { | void spiActivate() { | ||||
| m_spiDriver->activate(); | |||||
| m_spiDriver.activate(); | |||||
| } | |||||
| void spiBegin(SdSpiConfig spiConfig) { | |||||
| m_spiDriver.begin(spiConfig); | |||||
| } | } | ||||
| void spiDeactivate() { | void spiDeactivate() { | ||||
| m_spiDriver->deactivate(); | |||||
| m_spiDriver.deactivate(); | |||||
| } | } | ||||
| uint8_t spiReceive() { | uint8_t spiReceive() { | ||||
| return m_spiDriver->receive(); | |||||
| return m_spiDriver.receive(); | |||||
| } | } | ||||
| uint8_t spiReceive(uint8_t* buf, size_t n) { | 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) { | void spiSend(uint8_t data) { | ||||
| m_spiDriver->send(data); | |||||
| m_spiDriver.send(data); | |||||
| } | } | ||||
| void spiSend(const uint8_t* buf, size_t n) { | 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 | #if ENABLE_DEDICATED_SPI | ||||
| static const uint8_t IDLE_STATE = 0; | static const uint8_t IDLE_STATE = 0; | ||||
| static const uint8_t READ_STATE = 1; | static const uint8_t READ_STATE = 1; | ||||
| uint8_t m_curState; | uint8_t m_curState; | ||||
| bool m_sharedSpi; | bool m_sharedSpi; | ||||
| #endif // ENABLE_DEDICATED_SPI | #endif // ENABLE_DEDICATED_SPI | ||||
| SdSpiDriver *m_spiDriver; | |||||
| SdCsPin_t m_csPin; | SdCsPin_t m_csPin; | ||||
| uint8_t m_errorCode; | uint8_t m_errorCode; | ||||
| bool m_spiActive; | bool m_spiActive; |
| #define ENABLE_ARDUINO_SERIAL 1 | #define ENABLE_ARDUINO_SERIAL 1 | ||||
| /** For Debug - must be one */ | /** For Debug - must be one */ | ||||
| #define ENABLE_ARDUINO_STRING 1 | #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 | #define USE_BLOCK_DEVICE_INTERFACE 0 | ||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| #if ENABLE_ARDUINO_FEATURES | #if ENABLE_ARDUINO_FEATURES | ||||
| #include "Arduino.h" | #include "Arduino.h" | ||||
| #ifdef PLATFORM_ID | #ifdef PLATFORM_ID | ||||
| // Only defined if a Particle device | |||||
| // Only defined if a Particle device. | |||||
| #include "application.h" | #include "application.h" | ||||
| #endif // PLATFORM_ID | #endif // PLATFORM_ID | ||||
| #endif // ENABLE_ARDUINO_FEATURES | #endif // ENABLE_ARDUINO_FEATURES | ||||
| #define INCLUDE_SDIOS 0 | #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 | #define USE_FAT_FILE_FLAG_CONTIGUOUS 1 | ||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| * | * | ||||
| * 1 - The standard library driver is always used. | * 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 | #define SPI_DRIVER_SELECT 0 | ||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
| } | } | ||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| void SdSpiArduinoDriver::send(const uint8_t *buf, size_t count) { | 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 | uint32_t myArray[count/4]; // NOLINT | ||||
| for (int x = 0; x < count/4; x++) { | for (int x = 0; x < count/4; x++) { | ||||
| myArray[x] = ((uint32_t)buf[(x * 4) + 3] << (8 * 3)) | | myArray[x] = ((uint32_t)buf[(x * 4) + 3] << (8 * 3)) | |
| /** Activate SPI hardware. */ | /** Activate SPI hardware. */ | ||||
| virtual void activate() {} | virtual void activate() {} | ||||
| /** Initialize the SPI bus. */ | /** Initialize the SPI bus. */ | ||||
| virtual void begin() = 0; | |||||
| virtual void begin(SdSpiConfig config) = 0; | |||||
| /** Deactivate SPI hardware. */ | /** Deactivate SPI hardware. */ | ||||
| virtual void deactivate() {} | virtual void deactivate() {} | ||||
| /** Receive a byte. | /** Receive a byte. | ||||
| */ | */ | ||||
| virtual void setSckSpeed(uint32_t maxSck) {(void)maxSck;} | 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 | #endif // SdSpiBaseClass_h |
| void sdCsWrite(SdCsPin_t pin, bool level) { | void sdCsWrite(SdCsPin_t pin, bool level) { | ||||
| digitalWrite(pin, level); | digitalWrite(pin, level); | ||||
| } | } | ||||
| //------------------------------------------------------------------------------ | |||||
| #elif SD_CHIP_SELECT_MODE == 1 | #elif SD_CHIP_SELECT_MODE == 1 | ||||
| //------------------------------------------------------------------------------ | |||||
| __attribute__((weak)) | __attribute__((weak)) | ||||
| void sdCsInit(SdCsPin_t pin) { | void sdCsInit(SdCsPin_t pin) { | ||||
| pinMode(pin, OUTPUT); | pinMode(pin, OUTPUT); |
| #define SD_SCK_HZ(maxSpeed) (maxSpeed) | #define SD_SCK_HZ(maxSpeed) (maxSpeed) | ||||
| /** SPISettings for SCK frequency in MHz. */ | /** SPISettings for SCK frequency in MHz. */ | ||||
| #define SD_SCK_MHZ(maxMhz) (1000000UL*(maxMhz)) | #define SD_SCK_MHZ(maxMhz) (1000000UL*(maxMhz)) | ||||
| // SPI divisor constants | |||||
| // SPI divisor constants - obsolete. | |||||
| /** Set SCK to max rate. */ | /** Set SCK to max rate. */ | ||||
| #define SPI_FULL_SPEED SD_SCK_MHZ(50) | #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. */ | /** The SD is the only device on the SPI bus. */ | ||||
| #define DEDICATED_SPI 0X80 | #define DEDICATED_SPI 0X80 | ||||
| #define SHARED_SPI 0 | #define SHARED_SPI 0 | ||||
| #if SPI_DRIVER_SELECT < 2 | #if SPI_DRIVER_SELECT < 2 | ||||
| #include "SPI.h" | #include "SPI.h" | ||||
| /** Port type for SPI hardware driver. */ | |||||
| /** Port type for Arduino SPI hardware driver. */ | |||||
| typedef SPIClass SpiPort_t; | typedef SPIClass SpiPort_t; | ||||
| #elif SPI_DRIVER_SELECT == 2 | #elif SPI_DRIVER_SELECT == 2 | ||||
| class SoftSPIClass; | |||||
| class SdSpiSoftDriver; | |||||
| /** Port type for software SPI driver. */ | /** 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; | typedef SdSpiBaseClass SpiPort_t; | ||||
| #else // SPI_DRIVER_SELECT | |||||
| typedef void* SpiPort_t; | |||||
| #endif // SPI_DRIVER_SELECT | #endif // SPI_DRIVER_SELECT | ||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| /** | /** | ||||
| * \param[in] opt Options. | * \param[in] opt Options. | ||||
| */ | */ | ||||
| SdSpiConfig(SdCsPin_t cs, uint8_t opt) : | 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. | /** SdSpiConfig constructor. | ||||
| * | * | ||||
| * \param[in] cs Chip select pin. | * \param[in] cs Chip select pin. | ||||
| */ | */ | ||||
| explicit SdSpiConfig(SdCsPin_t cs) : csPin(cs), options(SHARED_SPI), | 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. */ | /** Chip select pin. */ | ||||
| const SdCsPin_t csPin; | const SdCsPin_t csPin; | ||||
| /** SPI port */ | /** SPI port */ | ||||
| SpiPort_t* spiPort; | SpiPort_t* spiPort; | ||||
| }; | }; | ||||
| #if SPI_DRIVER_SELECT < 2 | #if SPI_DRIVER_SELECT < 2 | ||||
| #include "SdSpiArduinoDriver.h" | #include "SdSpiArduinoDriver.h" | ||||
| #elif SPI_DRIVER_SELECT == 2 | #elif SPI_DRIVER_SELECT == 2 | ||||
| #include "SdSpiSoftDriver.h" | #include "SdSpiSoftDriver.h" | ||||
| #elif SPI_DRIVER_SELECT == 3 | #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 | #else // SPI_DRIVER_SELECT | ||||
| #error Invalid SPI_DRIVER_SELECT | #error Invalid SPI_DRIVER_SELECT | ||||
| #endif // SPI_DRIVER_SELECT | #endif // SPI_DRIVER_SELECT |
| /** | |||||
| * 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 |
| #define SdSpiSoftDriver_h | #define SdSpiSoftDriver_h | ||||
| #include "../DigitalIO/SoftSPI.h" | #include "../DigitalIO/SoftSPI.h" | ||||
| /** | /** | ||||
| * \class SoftSPIClass | |||||
| * \class SdSpiSoftDriver | |||||
| * \brief Base class for external soft SPI. | * \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: | public: | ||||
| /** Activate SPI hardware. */ | /** Activate SPI hardware. */ | ||||
| void activate() {} | void activate() {} | ||||
| /** Initialize the SPI bus. */ | |||||
| virtual void begin() = 0; | |||||
| /** Initialize the SPI bus. | /** Initialize the SPI bus. | ||||
| * | * | ||||
| * \param[in] spiConfig SD card configuration. | * \param[in] spiConfig SD card configuration. | ||||
| */ | */ | ||||
| void begin(SdSpiConfig spiConfig) { | void begin(SdSpiConfig spiConfig) { | ||||
| m_spi = spiConfig.spiPort; | |||||
| if (m_spi) m_spi->begin(); | |||||
| (void)spiConfig; | |||||
| begin(); | |||||
| } | } | ||||
| /** Deactivate SPI hardware. */ | /** Deactivate SPI hardware. */ | ||||
| void deactivate() {} | void deactivate() {} | ||||
| * | * | ||||
| * \return The byte. | * \return The byte. | ||||
| */ | */ | ||||
| uint8_t receive() {return m_spi ? m_spi->receive() : 0XFF;} | |||||
| virtual uint8_t receive() = 0; | |||||
| /** Receive multiple bytes. | /** 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) { | uint8_t receive(uint8_t* buf, size_t count) { | ||||
| for (size_t i = 0; i < count; i++) { | for (size_t i = 0; i < count; i++) { | ||||
| buf[i] = receive(); | buf[i] = receive(); | ||||
| * | * | ||||
| * \param[in] data Byte to send | * \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. | /** Send multiple bytes. | ||||
| * | * | ||||
| * \param[in] buf Buffer for data to be sent. | * \param[in] buf Buffer for data to be sent. | ||||
| void setSckSpeed(uint32_t maxSck) { | void setSckSpeed(uint32_t maxSck) { | ||||
| (void)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: | private: | ||||
| SoftSPIClass* m_spi; | |||||
| SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi; | |||||
| }; | }; | ||||
| /** Typedef for use of SdSoftSpiDriver */ | /** Typedef for use of SdSoftSpiDriver */ | ||||
| typedef SdSoftSpiDriver SdSpiDriver; | |||||
| typedef SdSpiSoftDriver SdSpiDriver; | |||||
| #endif // SdSpiSoftDriver_h | #endif // SdSpiSoftDriver_h |