| return false; | 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 = (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; | |||||
| fail: | |||||
| chipSelectHigh(); | |||||
| return false; | |||||
| } | |||||
| //------------------------------------------------------------------------------ | |||||
| /** read CID or CSR register */ | /** read CID or CSR register */ | ||||
| bool Sd2Card::readRegister(uint8_t cmd, void* buf) { | bool Sd2Card::readRegister(uint8_t cmd, void* buf) { | ||||
| uint8_t* dst = reinterpret_cast<uint8_t*>(buf); | uint8_t* dst = reinterpret_cast<uint8_t*>(buf); |
| return readRegister(CMD9, csd); | return readRegister(CMD9, csd); | ||||
| } | } | ||||
| bool readData(uint8_t *dst); | bool readData(uint8_t *dst); | ||||
| bool readOCR(uint32_t* ocr); | |||||
| bool readStart(uint32_t blockNumber); | bool readStart(uint32_t blockNumber); | ||||
| bool readStop(); | bool readStop(); | ||||
| /** Return SCK divisor. | /** Return SCK divisor. |
| * successfully opened and is not read only, its length shall be truncated to 0. | * 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 | * 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 | * \note Directory files must be opened read only. Write and truncation is | ||||
| * not allowed for directory files. | * not allowed for directory files. |
| #define DBG_FAIL_MACRO // Serial.print(__FILE__);Serial.println(__LINE__) | #define DBG_FAIL_MACRO // Serial.print(__FILE__);Serial.println(__LINE__) | ||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| /** SdFat version YYYYMMDD */ | /** SdFat version YYYYMMDD */ | ||||
| #define SD_FAT_VERSION 20140824 | |||||
| #define SD_FAT_VERSION 20141023 | |||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| /** error if old IDE */ | /** error if old IDE */ | ||||
| #if !defined(ARDUINO) || ARDUINO < 100 | #if !defined(ARDUINO) || ARDUINO < 100 |
| */ | */ | ||||
| #if defined(RAMEND) && RAMEND < 3000 | #if defined(RAMEND) && RAMEND < 3000 | ||||
| #define USE_MULTI_BLOCK_SD_IO 0 | #define USE_MULTI_BLOCK_SD_IO 0 | ||||
| #else | |||||
| #else // RAMEND | |||||
| #define USE_MULTI_BLOCK_SD_IO 1 | #define USE_MULTI_BLOCK_SD_IO 1 | ||||
| #endif | |||||
| #endif // RAMEND | |||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| /** | /** |
| * \file | * \file | ||||
| * \brief SdFile class | * \brief SdFile class | ||||
| */ | */ | ||||
| #include <SdBaseFile.h> | |||||
| #ifndef SdFile_h | #ifndef SdFile_h | ||||
| #define SdFile_h | #define SdFile_h | ||||
| #include <limits.h> | |||||
| #include <SdBaseFile.h> | |||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
| /** | /** | ||||
| * \class SdFile | * \class SdFile | ||||
| * \brief SdBaseFile with Print. | * \brief SdBaseFile with Print. | ||||
| */ | */ | ||||
| class SdFile : public SdBaseFile, public Print { | |||||
| class SdFile : public SdBaseFile, public Stream { | |||||
| public: | public: | ||||
| SdFile() {} | SdFile() {} | ||||
| SdFile(const char* name, uint8_t oflag); | SdFile(const char* name, uint8_t oflag); | ||||
| #if DESTRUCTOR_CLOSES_FILE | #if DESTRUCTOR_CLOSES_FILE | ||||
| ~SdFile() {} | ~SdFile() {} | ||||
| #endif // DESTRUCTOR_CLOSES_FILE | #endif // DESTRUCTOR_CLOSES_FILE | ||||
| /** \return number of bytes available from the current position to EOF | |||||
| * or INT_MAX if more than INT_MAX bytes are available. | |||||
| */ | |||||
| int available() { | |||||
| uint32_t n = SdBaseFile::available(); | |||||
| return n > INT_MAX ? INT_MAX : n; | |||||
| } | |||||
| /** Ensure that any bytes written to the file are saved to the SD card. */ | |||||
| void flush() {SdBaseFile::sync();} | |||||
| /** Return the next available byte without consuming it. | |||||
| * | |||||
| * \return The byte if no error and not at eof else -1; | |||||
| */ | |||||
| int peek() {return SdBaseFile::peek();} | |||||
| /** Read the next byte from a file. | |||||
| * | |||||
| * \return For success read returns the next byte in the file as an int. | |||||
| * If an error occurs or end of file is reached -1 is returned. | |||||
| */ | |||||
| int read() {return SdBaseFile::read();} | |||||
| /** \return value of writeError */ | /** \return value of writeError */ | ||||
| bool getWriteError() {return SdBaseFile::getWriteError();} | bool getWriteError() {return SdBaseFile::getWriteError();} | ||||
| /** Set writeError to zero */ | /** Set writeError to zero */ |
| sdErrorMsg("read MBR failed"); | sdErrorMsg("read MBR failed"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| for (uint8_t ip = 1; ip < 5; ip++) { | |||||
| part_t *pt = &p->mbr.part[ip - 1]; | |||||
| if ((pt->boot & 0X7F) != 0 || pt->firstSector > cardSize) { | |||||
| cout << pstr("\nNo MBR. Assuming Super Floppy format.\n"); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| cout << pstr("\nSD Partition Table\n"); | cout << pstr("\nSD Partition Table\n"); | ||||
| cout << pstr("part,boot,type,start,length\n"); | cout << pstr("part,boot,type,start,length\n"); | ||||
| for (uint8_t ip = 1; ip < 5; ip++) { | for (uint8_t ip = 1; ip < 5; ip++) { | ||||
| } | } | ||||
| if (!cidDmp()) return; | if (!cidDmp()) return; | ||||
| if (!csdDmp()) return; | if (!csdDmp()) return; | ||||
| uint32_t ocr; | |||||
| if (!card.readOCR(&ocr)) { | |||||
| sdErrorMsg("\nreadOCR failed"); | |||||
| return; | |||||
| } | |||||
| cout << pstr("OCR: ") << hex << ocr << dec << endl; | |||||
| if (!partDmp()) return; | if (!partDmp()) return; | ||||
| if (!vol.init(&card)) { | if (!vol.init(&card)) { | ||||
| sdErrorMsg("\nvol.init failed"); | sdErrorMsg("\nvol.init failed"); |
| * \return the stream | * \return the stream | ||||
| */ | */ | ||||
| ostream &operator<< (long arg) { // NOLINT | ostream &operator<< (long arg) { // NOLINT | ||||
| putNum(arg); | |||||
| putNum((int32_t)arg); | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| /** Output unsigned long | /** Output unsigned long | ||||
| * \return the stream | * \return the stream | ||||
| */ | */ | ||||
| ostream &operator<< (unsigned long arg) { // NOLINT | ostream &operator<< (unsigned long arg) { // NOLINT | ||||
| putNum(arg); | |||||
| putNum((uint32_t)arg); | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| /** Output pointer | /** Output pointer |