From 5325fa7627f64efdc08acbdaa1e9395d914229e1 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 20:24:40 -0800 Subject: [PATCH 1/8] We now have an in-memory mock (test double) for the file system! --- .gitignore | 1 + src/File_CI.cpp | 227 ++++++------------------------------------------ src/SD_CI.cpp | 107 ++++++++--------------- src/SD_CI.h | 119 ++++++++++++------------- test/test.cpp | 156 ++++++++++++++------------------- 5 files changed, 184 insertions(+), 426 deletions(-) diff --git a/.gitignore b/.gitignore index 32a2490..9343ab4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ Gemfile.lock .bundle vendor *.cpp.bin* +.vscode diff --git a/src/File_CI.cpp b/src/File_CI.cpp index 7168712..3af9bf0 100644 --- a/src/File_CI.cpp +++ b/src/File_CI.cpp @@ -6,101 +6,47 @@ #include #include #include -// #include namespace SDLib { -// File_CI::File_CI(File_Base *baseFile) { -// // this->baseFile = baseFile; -// } - -// File_CI::File_CI(SdFile f, const char *name) : File_Base(f, name) {} - -// File_CI::File_CI(void) : File_Base() {} - -File_CI::File_CI(const char *name, uint8_t mode = FILE_READ) { +File_CI::File_CI(const char *name, uint8_t mode) { + _path = name; _mode = mode; - strcpy(_path, name); - - // prepend base path - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, name); - - // does path exist? - if (fs::exists(newPath)) { - // if so, is it a directory? - if (fs::is_directory(newPath)) { - // if so, return a new object with the _isDirectory flag set - _isDirectory = true; - } else { - // path is an existing file - _isDirectory = false; - // if file is read, open for read - if (_mode == FILE_READ) { - finOut = new std::fstream; - finOut->open(newPath, std::fstream::binary | std::fstream::in); - } else if (_mode == FILE_WRITE) { - // else if mode is FILE_WRITE open for read and write - finOut = new std::fstream; - finOut->open(newPath, std::fstream::binary | std::fstream::in | - std::fstream::out | std::fstream::app); + _isOpen = true; + _pos = 0; + if (SD_CI.dirExists(name)) { + _isDir = true; + } else { + _isDir = false; + assert(mode & O_CREAT || SD_CI.fileExists(name)); + pContents = SD_CI.contentsOfNewOrExistingFileWithName(name); + if (mode & O_WRITE) { + if (mode & O_APPEND) { + _pos = pContents->size(); } else { - // else invalid mode, assert false - assert(false); + *pContents = ""; } - _open = true; - } - } else { - // path does not exist - _isDirectory = false; - // if mode is write, open new file - if (_mode == FILE_WRITE) { - finOut = new std::fstream; - finOut->open(newPath, std::fstream::binary | std::fstream::in | - std::fstream::out | std::fstream::app); - _open = true; - } else if (_mode == FILE_READ) { - // else assert false for file doesn't exist - assert(false); - } else { - // else invalid mode. assert false - assert(false); } } } -File_CI::~File_CI() { - if (!_isDirectory) { - delete finOut; +int File_CI::peek() { + if (_pos < pContents->size()) { + return pContents->at(_pos); + } else { + return EOF; } } -// size_t File_CI::write(uint8_t value) { -// // TODO -// // return File_Base::write(value); -// } - size_t File_CI::write(const char *buf, size_t size) { - // halt if file is directory - if (_isDirectory) { - assert(false); - } - - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, _path); - assert(_mode == FILE_WRITE); - finOut->write(buf, size); + for (int i = 0; i < size; ++i) { + *pContents += buf[i]; + } + _pos += size; return size; } -int File_CI::availableForWrite() { - // TODO - // return File_Base::availableForWrite(); -} - /* Note for read(): the user of this function needs to append their own null character to the end of the char array. This function will attempt to insert the number of bytes @@ -110,131 +56,12 @@ int File_CI::availableForWrite() { this function is used. */ int File_CI::read(char *buf, size_t size) { - // halt if file is directory - if (_isDirectory) { - assert(false); - } - - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, _path); - - int remaining = fs::file_size(newPath) - finOut->tellg(); - // if size is greater than remaining, use remaining for read - if (size > remaining) { - finOut->read(buf, remaining); - } else { - // else use size - finOut->read(buf, size); - } - return 0; -} - -int File_CI::peek() { - // halt if file is directory - if (_isDirectory) { - assert(false); - } - - char byte[2]; - // save old pointer position - fpos_t oldPos = finOut->tellg(); - // read in first char - finOut->read(byte, 1); - byte[1] = '\0'; - // put file pointer back - finOut->seekg(oldPos); - - // if file pointer isn't back, assert false - if (finOut->tellg() != oldPos) { - assert(false); - } - // return first char in buffer - return byte[0]; -} - -int File_CI::available() { - // halt if file is directory - if (_isDirectory) { - assert(false); - } - - // prepend base file path - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, _path); - - return fs::file_size(newPath); -} - -void File_CI::flush() { - // return File_Base::flush(); -} - -bool File_CI::seek(uint32_t pos) { - // halt if file is directory - if (_isDirectory) { - assert(false); - } - - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, _path); - - // if pos is greater than size - 1, return false - if (pos > fs::file_size(newPath) - 1) { - // trying to seek outside of file scope - return false; - } else { - finOut->seekg(pos); - } - // check for success - if (finOut->tellg() == pos) { - return true; - } - return false; -} - -uint32_t File_CI::position() { - // halt if file is directory - if (_isDirectory) { - assert(false); - } - - return finOut->tellg(); -} - -uint32_t File_CI::size() { - // halt if file is directory - if (_isDirectory) { - assert(false); - } - - // prepend base file path - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, _path); - return fs::file_size(newPath); -} - -void File_CI::close() { - // close if not directory - if (!_isDirectory) { - finOut->close(); - } - _open = false; -} - -File_CI File_CI::openNextFile(uint8_t mode = FILE_READ) { - // TODO + size = size <= available() ? size : available(); + memcpy(buf, pContents->c_str() + _pos, size); + _pos += size; + return size; } -char *File_CI::name() { return _path; } - -File_CI::operator bool() { return File_Base::operator bool(); } - -bool File_CI::isDirectory(void) { return _isDirectory; } - } // namespace SDLib #endif diff --git a/src/SD_CI.cpp b/src/SD_CI.cpp index d833e1c..77636e2 100644 --- a/src/SD_CI.cpp +++ b/src/SD_CI.cpp @@ -1,94 +1,57 @@ #include #ifdef MOCK_PINS_COUNT #include "SD_CI.h" - -#include -#include -#include #include -#include -#include -#include namespace SDLib { -void File_CI::rewindDirectory(void) { - // File_Base::rewindDirectory(); -} - -// ================================================================= - -bool SDClass_CI::begin(uint8_t csPin) { - // return SDClass_Base::begin(csPin); -} - -bool SDClass_CI::begin(uint32_t clock, uint8_t csPin) { - // return SDClass_Base::begin(clock, csPin); -} - -void SDClass_CI::end() { - // SDClass_Base::end(); -} - -File_CI SDClass_CI::open(const char *filename, uint8_t mode) { - return File_CI(filename, mode); -} - -bool SDClass_CI::exists(const char *filepath) { - // prepend base file path - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, filepath); - - return fs::exists(newPath); +std::string * +SDClass_CI::contentsOfNewOrExistingFileWithName(const char *filepath) { + if (!fileExists(filepath)) { + files.emplace(std::string(filepath), new std::string); + } + return files[filepath]; } bool SDClass_CI::mkdir(const char *filepath) { - // prepend base file path - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, filepath); - - if (strchr(filepath, '/') == nullptr) { - // Creating a single directory - try { - fs::create_directory(newPath); - } catch (fs::filesystem_error &excpt) { - std::cerr << excpt.what() << std::endl; - return false; - } - return true; - } else { - // creating multiple directories - try { - fs::create_directories(newPath); - } catch (fs::filesystem_error &excpt) { - std::cerr << excpt.what() << std::endl; - return false; - } - return true; + assert(!fileExists(filepath)); + if (dirExists(filepath)) { + return false; + } + char *path = new char[strlen(filepath) + 1]; + strcpy(path, filepath); + char *ptr = strchr(path, '/'); + while (ptr) { + *ptr = '\0'; + directories.insert(path); + *ptr = '/'; + ptr = strchr(ptr + 1, '/'); } + directories.insert(filepath); + delete path; + return true; } bool SDClass_CI::remove(const char *filepath) { - // prepend base file path - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, filepath); - - return fs::remove(newPath); + if (files.count(filepath)) { + delete files[filepath]; + files.erase(filepath); + return true; + } + return false; } bool SDClass_CI::rmdir(const char *filepath) { - // prepend base file path - char newPath[FILE_PATH_SIZE]; - strcpy(newPath, BASE_PATH); - strcat(newPath, filepath); - - return fs::remove_all(newPath); + if (directories.count(filepath)) { + directories.erase(filepath); + return true; + } + return false; } -SDClass_CI sd_ci; +SDClass_CI SD_CI; +std::set SDClass_CI::directories; +std::map SDClass_CI::files; } // namespace SDLib diff --git a/src/SD_CI.h b/src/SD_CI.h index 67fc2fb..4ed7031 100644 --- a/src/SD_CI.h +++ b/src/SD_CI.h @@ -1,50 +1,34 @@ #pragma once #include #ifdef MOCK_PINS_COUNT -#include -#include -#include - -namespace fs = std::filesystem; +#include "SD.h" +#include +#include +#include +#include namespace SDLib { -#define BASE_PATH "fileSystem/" -#define FILE_PATH_SIZE 255 - class File_CI : public File_Base { -private: - std::fstream *finOut; - // int _pos; - char _path[FILE_PATH_SIZE]; - uint8_t _mode; - bool _open; - bool _isDirectory; - public: - // File_CI(File_Base *baseFile); - // File_CI(SdFile f, const char *name); // wraps an underlying SdFile - // File_CI(void); // 'empty' constructor File_CI(const char *name, uint8_t mode); - ~File_CI(); - // template size_t write1(T data); - virtual size_t write(const char *buf, size_t size); - virtual int availableForWrite(); - virtual int peek(); - virtual int available(); - virtual void flush(); + size_t write(const char *buf, size_t size); + int availableForWrite() { return 4096; } + int peek(); + int available() { return pContents->size() - _pos; } + void flush() {} int read(char *buf, size_t size); - bool seek(uint32_t pos); - uint32_t position(); - uint32_t size(); - void close(); - operator bool(); - char *name(); - bool isOpen() { return _open; } - - bool isDirectory(void); - File_CI openNextFile(uint8_t mode); - void rewindDirectory(void); + bool seek(uint32_t pos) { return _pos = pos <= size() ? pos : size(); } + uint32_t position() { return _pos; } + uint32_t size() { return pContents->size(); } + void close() { _isOpen = false; } + operator bool() { return _isOpen; } + const char *name() { return _path.c_str(); } + bool isOpen() { return _isOpen; } + + bool isDirectory(void) { return _isDir; } + File_CI openNextFile(uint8_t mode) { assert(false); } + void rewindDirectory(void) { assert(false); } using Print::write; // testing functions @@ -53,53 +37,64 @@ class File_CI : public File_Base { void clearWriteError() { writeError = 0; } private: + std::string *pContents; + int _pos; // index of _next_ char to read or write + std::string _path; + uint8_t _mode; + bool _isOpen; + bool _isDir; int writeError; }; class SDClass_CI : public SDClass_Base { - -private: public: - // This needs to be called to set up the connection to the SD card - // before other methods are used. - bool begin(uint8_t csPin = SD_CHIP_SELECT_PIN); - bool begin(uint32_t clock, uint8_t csPin); - - // call this when a card is removed. It will allow you to insert and - // initialise a new card. - void end(); - - // Open the specified file/directory with the supplied mode (e.g. read or - // write, etc). Returns a File object for interacting with the file. - // Note that currently only one file can be open at a time. - File_CI open(const char *filename, uint8_t mode); - File_CI open(const String &filename, uint8_t mode = FILE_READ) { - return open(filename.c_str(), mode); + // Ignore hardware-related setup + bool begin(uint8_t csPin = SD_CHIP_SELECT_PIN) { return true; } + bool begin(uint32_t clock, uint8_t csPin) { return true; } + void end() {} + + std::string *contentsOfNewOrExistingFileWithName(const char *filepath); + bool dirExists(const char *filepath) { + std::cout << "dirExists(\"" << filepath + << "\") == " << directories.count(filepath) << std::endl; + return directories.count(filepath) == 1; + } + bool exists(const char *filepath) { + // This doesn't check directories for intermediate paths + return files.count(filepath) || dirExists(filepath); } - - // Methods to determine if the requested file path exists. - bool exists(const char *filepath); bool exists(const String &filepath) { return exists(filepath.c_str()); } + bool fileExists(const char *filepath) { return files.count(filepath); } - // Create the requested directory heirarchy--if intermediate directories - // do not exist they will be created. bool mkdir(const char *filepath); bool mkdir(const String &filepath) { return mkdir(filepath.c_str()); } - // Delete the file. + File_CI open(const char *filename, uint8_t mode) { + return File_CI(filename, mode); + } + File_CI open(const String &filename, uint8_t mode = FILE_READ) { + return open(filename.c_str(), mode); + } + bool remove(const char *filepath); bool remove(const String &filepath) { return remove(filepath.c_str()); } + void removeAll() { + directories.clear(); + files.clear(); + } + bool rmdir(const char *filepath); bool rmdir(const String &filepath) { return rmdir(filepath.c_str()); } virtual String className() const { return "SDClass_Base"; } private: - friend class File; + static std::set directories; + static std::map files; }; -extern SDClass_CI sd_ci; +extern SDClass_CI SD_CI; } // namespace SDLib diff --git a/test/test.cpp b/test/test.cpp index d789f9a..8211223 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -9,102 +9,96 @@ bundle exec arduino_ci.rb --skip-unittests #include "SD_CI.h" #include -unittest(exists_works) { - assertFalse(sd_ci.exists("noSuchFile.txt")); - File_CI existingFile = sd_ci.open("existingFile.txt", FILE_WRITE); +unittest_setup() { SD_CI.removeAll(); } + +unittest_teardown() { SD_CI.removeAll(); } + +unittest(exists) { + assertFalse(SD_CI.exists("noSuchFile.txt")); + File_CI existingFile = SD_CI.open("existingFile.txt", FILE_WRITE); existingFile.close(); - assertTrue(sd_ci.exists("existingFile.txt")); - sd_ci.remove("existingFile.txt"); + assertTrue(SD_CI.exists("existingFile.txt")); } -unittest(mkdir_works) { - assertTrue(sd_ci.mkdir("test_directory/a/b")); - assertTrue(sd_ci.mkdir("test_directory/a/c")); - assertTrue(sd_ci.exists("test_directory")); - assertTrue(sd_ci.exists("test_directory/a/b")); - assertTrue(sd_ci.exists("test_directory/a/c")); - - // tear down - sd_ci.rmdir("test_directory"); +unittest(mkdir) { + assertTrue(SD_CI.mkdir("test_directory/a/b")); + assertTrue(SD_CI.mkdir("test_directory/a/c")); + assertTrue(SD_CI.exists("test_directory")); + assertTrue(SD_CI.exists("test_directory/a/b")); + assertTrue(SD_CI.exists("test_directory/a/c")); } -unittest(open_works) { +unittest(open) { // create file - File_CI writeFile = sd_ci.open("file.txt", FILE_WRITE); + File_CI writeFile = SD_CI.open("file.txt", FILE_WRITE); writeFile.close(); // open file for read should exist - File_CI readFile2 = sd_ci.open("file.txt", FILE_READ); + File_CI readFile2 = SD_CI.open("file.txt", FILE_READ); assertTrue(readFile2.isOpen()); readFile2.close(); - // delete test file - sd_ci.remove("file.txt"); } -unittest(close_works) { +unittest(close) { // close write file - File_CI file = sd_ci.open("file.txt", FILE_WRITE); + File_CI file = SD_CI.open("file.txt", FILE_WRITE); assertTrue(file.isOpen()); file.close(); assertFalse(file.isOpen()); // close read file - File_CI readFile = sd_ci.open("file.txt", FILE_READ); + File_CI readFile = SD_CI.open("file.txt", FILE_READ); assertTrue(readFile.isOpen()); readFile.close(); assertFalse(readFile.isOpen()); - sd_ci.remove("file.txt"); } -unittest(remove_works) { +unittest(remove) { // set up - File_CI file = sd_ci.open("file.txt", FILE_WRITE); + File_CI file = SD_CI.open("file.txt", FILE_WRITE); file.close(); - assertTrue(sd_ci.exists("file.txt")); + assertTrue(SD_CI.exists("file.txt")); - sd_ci.remove("file.txt"); - assertFalse(sd_ci.exists("file.txt")); + SD_CI.remove("file.txt"); + assertFalse(SD_CI.exists("file.txt")); } -unittest(rmdir_works) { +unittest(rmdir) { // set up - sd_ci.mkdir("test_directory/a/a"); - sd_ci.mkdir("test_directory/a/b"); - sd_ci.mkdir("test_directory/a/c"); - File_CI file = sd_ci.open("test_directory/a/a/file.txt", FILE_WRITE); + SD_CI.mkdir("test_directory/a/a"); + SD_CI.mkdir("test_directory/a/b"); + SD_CI.mkdir("test_directory/a/c"); + File_CI file = SD_CI.open("test_directory/a/a/file.txt", FILE_WRITE); file.close(); // remove directory - assertTrue(sd_ci.rmdir("test_directory/a/c")); + assertTrue(SD_CI.rmdir("test_directory/a/c")); // make sure non-removed dirs still exist - assertTrue(sd_ci.exists("test_directory")); - assertTrue(sd_ci.exists("test_directory/a/a")); + assertTrue(SD_CI.exists("test_directory")); + assertTrue(SD_CI.exists("test_directory/a/a")); // make sure removed dir no longer exists - assertFalse(sd_ci.exists("test_directory/a/c")); + assertFalse(SD_CI.exists("test_directory/a/c")); // remove directory with sub directories - assertTrue(sd_ci.rmdir("test_directory")); - assertFalse(sd_ci.exists("test_directory")); + assertTrue(SD_CI.rmdir("test_directory")); + assertFalse(SD_CI.exists("test_directory")); } -unittest(name_works) { +unittest(name) { // set up - File_CI file = sd_ci.open("newFile.txt", FILE_WRITE); + File_CI file = SD_CI.open("newFile.txt", FILE_WRITE); char expected[] = "newFile.txt"; assertEqual(expected, file.name()); file.close(); - - // tear down - sd_ci.remove("newFile.txt"); } -unittest(seek_works) { +unittest(seek) { // set up - File_CI file = sd_ci.open("seek.txt", FILE_WRITE); + File_CI file = SD_CI.open("seek.txt", FILE_WRITE); char write[] = "Hide and Seek."; file.write(write, sizeof(write) - 1); file.close(); - File_CI read = sd_ci.open("seek.txt", FILE_READ); + File_CI read = SD_CI.open("seek.txt", FILE_READ); // Testing char readFrom[4]; @@ -113,25 +107,22 @@ unittest(seek_works) { read.read(readFrom, 3); readFrom[3] = '\0'; assertEqual(expected, readFrom); - - // tear down - sd_ci.remove("seek.txt"); } -unittest(read_works) { +unittest(read) { // set up - File_CI file = sd_ci.open("birthday.txt", FILE_WRITE); + File_CI file = SD_CI.open("birthday.txt", FILE_WRITE); char toWrite[] = "Happy Birthday to You!"; file.write(toWrite, sizeof(toWrite) - 1); file.close(); - File_CI file2 = sd_ci.open("lines.txt", FILE_WRITE); + File_CI file2 = SD_CI.open("lines.txt", FILE_WRITE); char toWrite2[] = "line 1\nline2"; file2.write(toWrite2, sizeof(toWrite2) - 1); file2.close(); // testing - File_CI readFile = sd_ci.open("birthday.txt", FILE_READ); + File_CI readFile = SD_CI.open("birthday.txt", FILE_READ); size_t size = readFile.size(); char readFromFile[size + 1]; readFile.read(readFromFile, size); @@ -140,7 +131,7 @@ unittest(read_works) { // assertEqual(toWrite, readFromFile); - File_CI readFile2 = sd_ci.open("lines.txt", FILE_READ); + File_CI readFile2 = SD_CI.open("lines.txt", FILE_READ); char readFromFile2[7 + 1]; char readFromFile3[5 + 1]; readFile2.read(readFromFile2, 7); @@ -152,15 +143,11 @@ unittest(read_works) { char expected3[] = "line2"; assertEqual(expected2, readFromFile2); assertEqual(expected3, readFromFile3); - - // tear down - sd_ci.remove("birthday.txt"); - sd_ci.remove("lines.txt"); } -unittest(write_works) { +unittest(write) { // open new file for writing - File_CI writeFile = sd_ci.open("wood.txt", FILE_WRITE); + File_CI writeFile = SD_CI.open("wood.txt", FILE_WRITE); char toWrite[] = "How much wood could a wood pecker peck?\n"; writeFile.write(toWrite, sizeof(toWrite) - 1); @@ -174,13 +161,13 @@ unittest(write_works) { writeFile.close(); // open old writing file to write at end. - File_CI writeFile2 = sd_ci.open("wood.txt", FILE_WRITE); + File_CI writeFile2 = SD_CI.open("wood.txt", FILE_WRITE); char toWrite2[] = "A lot of wood.\n"; writeFile2.write(toWrite2, sizeof(toWrite2) - 1); writeFile2.close(); // check old writing file - File_CI readWrite2 = sd_ci.open("wood.txt", FILE_READ); + File_CI readWrite2 = SD_CI.open("wood.txt", FILE_READ); size_t size2 = readWrite2.size(); char toRead2[size2 + 1]; readWrite2.read(toRead2, size2); @@ -189,14 +176,11 @@ unittest(write_works) { "How much wood could a wood pecker peck?\nA lot of wood.\n"; // assertEqual(expected2, toRead2); readWrite2.close(); - - // teardown - sd_ci.remove("wood.txt"); } -unittest(size_works) { +unittest(size) { // setup - File_CI sizeFile = sd_ci.open("size.txt", FILE_WRITE); + File_CI sizeFile = SD_CI.open("size.txt", FILE_WRITE); char toWrite[] = "Test text\n"; sizeFile.write(toWrite, sizeof(toWrite) - 1); sizeFile.close(); @@ -204,37 +188,31 @@ unittest(size_works) { // test uint32_t fileSize = sizeFile.size(); assertEqual(10, fileSize); - - // tear down - sd_ci.remove("size.txt"); } -unittest(peek_works) { +unittest(peek) { // set up - File_CI peekFile = sd_ci.open("peek.txt", FILE_WRITE); + File_CI peekFile = SD_CI.open("peek.txt", FILE_WRITE); char toWrite[] = "Peek file content\n"; peekFile.write(toWrite, sizeof(toWrite) - 1); peekFile.close(); // Test - File_CI readPeek = sd_ci.open("peek.txt", FILE_READ); + File_CI readPeek = SD_CI.open("peek.txt", FILE_READ); assertEqual('P', readPeek.peek()); assertEqual('P', readPeek.peek()); readPeek.close(); - File_CI readWritePeek = sd_ci.open("peek.txt", FILE_WRITE); + File_CI readWritePeek = SD_CI.open("peek.txt", FILE_WRITE); readWritePeek.seek(0); assertEqual('P', readWritePeek.peek()); assertEqual('P', readWritePeek.peek()); readWritePeek.close(); - - // tear down - sd_ci.remove("peek.txt"); } -unittest(position_works) { +unittest(position) { // set up - File_CI posFile = sd_ci.open("pos.txt", FILE_WRITE); + File_CI posFile = SD_CI.open("pos.txt", FILE_WRITE); char toWrite[] = "This is the position file.\n"; posFile.write(toWrite, sizeof(toWrite) - 1); @@ -243,21 +221,18 @@ unittest(position_works) { posFile.seek(5); assertEqual(5, posFile.position()); posFile.close(); - - // tear down - sd_ci.remove("pos.txt"); } -unittest(isDirectory_works) { +unittest(isDirectory) { // set up - sd_ci.mkdir("test"); - File_CI toRead = sd_ci.open("read.txt", FILE_WRITE); + SD_CI.mkdir("test"); + File_CI toRead = SD_CI.open("read.txt", FILE_WRITE); toRead.close(); - File_CI testFile = sd_ci.open("test.txt", FILE_WRITE); - File_CI readFile = sd_ci.open("read.txt", FILE_READ); + File_CI testFile = SD_CI.open("test.txt", FILE_WRITE); + File_CI readFile = SD_CI.open("read.txt", FILE_READ); // test - File_CI myDir = sd_ci.open("test"); + File_CI myDir = SD_CI.open("test"); assertTrue(myDir.isDirectory()); assertFalse(testFile.isDirectory()); assertFalse(readFile.isDirectory()); @@ -265,8 +240,5 @@ unittest(isDirectory_works) { // tear down testFile.close(); readFile.close(); - sd_ci.remove("test.txt"); - sd_ci.remove("read.txt"); - sd_ci.rmdir("test"); } unittest_main() From 0b75571ed01e81993d35c2198145a0fe3dfdc7d8 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 20:28:48 -0800 Subject: [PATCH 2/8] Add GitHub Action (fix #8) --- .github/workflows/arduino_ci.yml | 12 ++++++++++++ .github/workflows/format.yml | 15 +++++++++++++++ .gitignore | 1 + 3 files changed, 28 insertions(+) create mode 100644 .github/workflows/arduino_ci.yml create mode 100644 .github/workflows/format.yml diff --git a/.github/workflows/arduino_ci.yml b/.github/workflows/arduino_ci.yml new file mode 100644 index 0000000..a740665 --- /dev/null +++ b/.github/workflows/arduino_ci.yml @@ -0,0 +1,12 @@ +--- +name: Arduino CI + +on: [push, pull_request] + +jobs: + arduino_ci: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: Arduino-CI/action@stable-1.x diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..c8f556d --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,15 @@ +name: test-clang-format + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: DoozyX/clang-format-lint-action@v0.5 + with: + source: './' + extensions: 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx,ino' + clangFormatVersion: 9 diff --git a/.gitignore b/.gitignore index 32a2490..9343ab4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ Gemfile.lock .bundle vendor *.cpp.bin* +.vscode From 4a7dbe5ce42483784262525fb9e3408558cf4b3f Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 20:33:20 -0800 Subject: [PATCH 3/8] Update format. --- src/File.cpp | 30 +- src/SD.cpp | 810 +++++++++++++++---------------- src/utility/FatStructs.h | 72 +-- src/utility/Sd2Card.cpp | 183 +++---- src/utility/Sd2Card.h | 282 ++++++----- src/utility/Sd2PinMap.cpp | 2 +- src/utility/Sd2PinMap.h | 669 +++++++++++++------------- src/utility/SdFat.h | 918 +++++++++++++++++------------------- src/utility/SdFatUtil.h | 30 +- src/utility/SdFatmainpage.h | 38 +- src/utility/SdFile.cpp | 138 +++--- src/utility/SdInfo.h | 18 +- src/utility/SdVolume.cpp | 38 +- 13 files changed, 1558 insertions(+), 1670 deletions(-) diff --git a/src/File.cpp b/src/File.cpp index 4478ec1..e875bce 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -22,7 +22,7 @@ File_Base::File_Base(SdFile f, const char *n) { // oh man you are kidding me, new() doesn't exist? Ok we do it by hand! _file = (SdFile *)malloc(sizeof(SdFile)); if (_file) { - memcpy((void*)_file, (void*)&f, sizeof(SdFile)); + memcpy((void *)_file, (void *)&f, sizeof(SdFile)); strncpy(_name, n, 12); _name[12] = 0; @@ -40,23 +40,16 @@ File_Base::File_Base(SdFile f, const char *n) { File_Base::File_Base(void) { _file = 0; _name[0] = 0; - //Serial.print("Created empty file object"); + // Serial.print("Created empty file object"); } // returns a pointer to the file name -char *File_Base::name(void) { - return _name; -} +char *File_Base::name(void) { return _name; } // a directory is a special type of file -bool File_Base::isDirectory(void) { - return (_file && _file->isDir()); -} +bool File_Base::isDirectory(void) { return (_file && _file->isDir()); } - -size_t File_Base::write(uint8_t val) { - return write(&val, 1); -} +size_t File_Base::write(uint8_t val) { return write(&val, 1); } size_t File_Base::write(const uint8_t *buf, size_t size) { size_t t; @@ -81,7 +74,7 @@ int File_Base::availableForWrite() { } int File_Base::peek() { - if (! _file) { + if (!_file) { return 0; } @@ -108,7 +101,7 @@ int File_Base::read(void *buf, uint16_t nbyte) { } int File_Base::available() { - if (! _file) { + if (!_file) { return 0; } @@ -124,7 +117,7 @@ void File_Base::flush() { } bool File_Base::seek(uint32_t pos) { - if (! _file) { + if (!_file) { return false; } @@ -132,14 +125,14 @@ bool File_Base::seek(uint32_t pos) { } uint32_t File_Base::position() { - if (! _file) { + if (!_file) { return -1; } return _file->curPosition(); } uint32_t File_Base::size() { - if (! _file) { + if (!_file) { return 0; } return _file->fileSize(); @@ -161,8 +154,7 @@ void File_Base::close() { File_Base::operator bool() { if (_file) { - return _file->isOpen(); + return _file->isOpen(); } return false; } - diff --git a/src/SD.cpp b/src/SD.cpp index 636b608..3d18889 100644 --- a/src/SD.cpp +++ b/src/SD.cpp @@ -54,584 +54,558 @@ namespace SDLib { - // Used by `getNextPathComponent` +// Used by `getNextPathComponent` #define MAX_COMPONENT_LEN 12 // What is max length? -#define PATH_COMPONENT_BUFFER_LEN MAX_COMPONENT_LEN+1 - - bool getNextPathComponent(const char *path, unsigned int *p_offset, - char *buffer) { - /* - - Parse individual path components from a path. - - e.g. after repeated calls '/foo/bar/baz' will be split - into 'foo', 'bar', 'baz'. - - This is similar to `strtok()` but copies the component into the - supplied buffer rather than modifying the original string. +#define PATH_COMPONENT_BUFFER_LEN MAX_COMPONENT_LEN + 1 +bool getNextPathComponent(const char *path, unsigned int *p_offset, + char *buffer) { + /* - `buffer` needs to be PATH_COMPONENT_BUFFER_LEN in size. + Parse individual path components from a path. - `p_offset` needs to point to an integer of the offset at - which the previous path component finished. + e.g. after repeated calls '/foo/bar/baz' will be split + into 'foo', 'bar', 'baz'. - Returns `true` if more components remain. + This is similar to `strtok()` but copies the component into the + supplied buffer rather than modifying the original string. - Returns `false` if this is the last component. - (This means path ended with 'foo' or 'foo/'.) - */ + `buffer` needs to be PATH_COMPONENT_BUFFER_LEN in size. - // TODO: Have buffer local to this function, so we know it's the - // correct length? + `p_offset` needs to point to an integer of the offset at + which the previous path component finished. - int bufferOffset = 0; + Returns `true` if more components remain. - int offset = *p_offset; + Returns `false` if this is the last component. + (This means path ended with 'foo' or 'foo/'.) - // Skip root or other separator - if (path[offset] == '/') { - offset++; - } + */ - // Copy the next next path segment - while (bufferOffset < MAX_COMPONENT_LEN - && (path[offset] != '/') - && (path[offset] != '\0')) { - buffer[bufferOffset++] = path[offset++]; - } + // TODO: Have buffer local to this function, so we know it's the + // correct length? - buffer[bufferOffset] = '\0'; + int bufferOffset = 0; - // Skip trailing separator so we can determine if this - // is the last component in the path or not. - if (path[offset] == '/') { - offset++; - } + int offset = *p_offset; - *p_offset = offset; - - return (path[offset] != '\0'); + // Skip root or other separator + if (path[offset] == '/') { + offset++; } + // Copy the next next path segment + while (bufferOffset < MAX_COMPONENT_LEN && (path[offset] != '/') && + (path[offset] != '\0')) { + buffer[bufferOffset++] = path[offset++]; + } + buffer[bufferOffset] = '\0'; - bool walkPath(const char *filepath, SdFile& parentDir, - bool(*callback)(SdFile& parentDir, - const char *filePathComponent, - bool isLastComponent, - void *object), - void *object = NULL) { - /* - - When given a file path (and parent directory--normally root), - this function traverses the directories in the path and at each - level calls the supplied callback function while also providing - the supplied object for context if required. + // Skip trailing separator so we can determine if this + // is the last component in the path or not. + if (path[offset] == '/') { + offset++; + } - e.g. given the path '/foo/bar/baz' - the callback would be called at the equivalent of - '/foo', '/foo/bar' and '/foo/bar/baz'. + *p_offset = offset; - The implementation swaps between two different directory/file - handles as it traverses the directories and does not use recursion - in an attempt to use memory efficiently. + return (path[offset] != '\0'); +} - If a callback wishes to stop the directory traversal it should - return false--in this case the function will stop the traversal, - tidy up and return false. +bool walkPath(const char *filepath, SdFile &parentDir, + bool (*callback)(SdFile &parentDir, const char *filePathComponent, + bool isLastComponent, void *object), + void *object = NULL) { + /* - If a directory path doesn't exist at some point this function will - also return false and not subsequently call the callback. + When given a file path (and parent directory--normally root), + this function traverses the directories in the path and at each + level calls the supplied callback function while also providing + the supplied object for context if required. - If a directory path specified is complete, valid and the callback - did not indicate the traversal should be interrupted then this - function will return true. + e.g. given the path '/foo/bar/baz' + the callback would be called at the equivalent of + '/foo', '/foo/bar' and '/foo/bar/baz'. - */ + The implementation swaps between two different directory/file + handles as it traverses the directories and does not use recursion + in an attempt to use memory efficiently. + If a callback wishes to stop the directory traversal it should + return false--in this case the function will stop the traversal, + tidy up and return false. - SdFile subfile1; - SdFile subfile2; + If a directory path doesn't exist at some point this function will + also return false and not subsequently call the callback. - char buffer[PATH_COMPONENT_BUFFER_LEN]; + If a directory path specified is complete, valid and the callback + did not indicate the traversal should be interrupted then this + function will return true. - unsigned int offset = 0; + */ - SdFile *p_parent; - SdFile *p_child; + SdFile subfile1; + SdFile subfile2; - SdFile *p_tmp_sdfile; + char buffer[PATH_COMPONENT_BUFFER_LEN]; - p_child = &subfile1; + unsigned int offset = 0; - p_parent = &parentDir; + SdFile *p_parent; + SdFile *p_child; - while (true) { + SdFile *p_tmp_sdfile; - bool moreComponents = getNextPathComponent(filepath, &offset, buffer); + p_child = &subfile1; - bool shouldContinue = callback((*p_parent), buffer, !moreComponents, object); + p_parent = &parentDir; - if (!shouldContinue) { - // TODO: Don't repeat this code? - // If it's one we've created then we - // don't need the parent handle anymore. - if (p_parent != &parentDir) { - (*p_parent).close(); - } - return false; - } + while (true) { - if (!moreComponents) { - break; - } + bool moreComponents = getNextPathComponent(filepath, &offset, buffer); - bool exists = (*p_child).open(*p_parent, buffer, O_RDONLY); + bool shouldContinue = + callback((*p_parent), buffer, !moreComponents, object); + if (!shouldContinue) { + // TODO: Don't repeat this code? // If it's one we've created then we // don't need the parent handle anymore. if (p_parent != &parentDir) { (*p_parent).close(); } + return false; + } - // Handle case when it doesn't exist and we can't continue... - if (exists) { - // We alternate between two file handles as we go down - // the path. - if (p_parent == &parentDir) { - p_parent = &subfile2; - } - - p_tmp_sdfile = p_parent; - p_parent = p_child; - p_child = p_tmp_sdfile; - } else { - return false; - } + if (!moreComponents) { + break; } + bool exists = (*p_child).open(*p_parent, buffer, O_RDONLY); + + // If it's one we've created then we + // don't need the parent handle anymore. if (p_parent != &parentDir) { - (*p_parent).close(); // TODO: Return/ handle different? + (*p_parent).close(); } - return true; + // Handle case when it doesn't exist and we can't continue... + if (exists) { + // We alternate between two file handles as we go down + // the path. + if (p_parent == &parentDir) { + p_parent = &subfile2; + } + + p_tmp_sdfile = p_parent; + p_parent = p_child; + p_child = p_tmp_sdfile; + } else { + return false; + } } + if (p_parent != &parentDir) { + (*p_parent).close(); // TODO: Return/ handle different? + } + return true; +} - /* +/* - The callbacks used to implement various functionality follow. + The callbacks used to implement various functionality follow. - Each callback is supplied with a parent directory handle, - character string with the name of the current file path component, - a flag indicating if this component is the last in the path and - a pointer to an arbitrary object used for context. + Each callback is supplied with a parent directory handle, + character string with the name of the current file path component, + a flag indicating if this component is the last in the path and + a pointer to an arbitrary object used for context. - */ +*/ - bool callback_pathExists(SdFile& parentDir, const char *filePathComponent, - bool /* isLastComponent */, void * /* object */) { - /* +bool callback_pathExists(SdFile &parentDir, const char *filePathComponent, + bool /* isLastComponent */, void * /* object */) { + /* - Callback used to determine if a file/directory exists in parent - directory. + Callback used to determine if a file/directory exists in parent + directory. - Returns true if file path exists. + Returns true if file path exists. - */ - SdFile child; + */ + SdFile child; - bool exists = child.open(parentDir, filePathComponent, O_RDONLY); + bool exists = child.open(parentDir, filePathComponent, O_RDONLY); - if (exists) { - child.close(); - } - - return exists; + if (exists) { + child.close(); } + return exists; +} +bool callback_makeDirPath(SdFile &parentDir, const char *filePathComponent, + bool isLastComponent, void *object) { + /* - bool callback_makeDirPath(SdFile& parentDir, const char *filePathComponent, - bool isLastComponent, void *object) { - /* - - Callback used to create a directory in the parent directory if - it does not already exist. - - Returns true if a directory was created or it already existed. + Callback used to create a directory in the parent directory if + it does not already exist. - */ - bool result = false; - SdFile child; + Returns true if a directory was created or it already existed. - result = callback_pathExists(parentDir, filePathComponent, isLastComponent, object); - if (!result) { - result = child.makeDir(parentDir, filePathComponent); - } + */ + bool result = false; + SdFile child; - return result; + result = callback_pathExists(parentDir, filePathComponent, isLastComponent, + object); + if (!result) { + result = child.makeDir(parentDir, filePathComponent); } + return result; +} - /* - - bool callback_openPath(SdFile& parentDir, char *filePathComponent, - bool isLastComponent, void *object) { - - Callback used to open a file specified by a filepath that may - specify one or more directories above it. - - Expects the context object to be an instance of `SDClass_Base` and - will use the `file` property of the instance to open the requested - file/directory with the associated file open mode property. +/* - Always returns true if the directory traversal hasn't reached the - bottom of the directory hierarchy. + bool callback_openPath(SdFile& parentDir, char *filePathComponent, + bool isLastComponent, void *object) { - Returns false once the file has been opened--to prevent the traversal - from descending further. (This may be unnecessary.) + Callback used to open a file specified by a filepath that may + specify one or more directories above it. - if (isLastComponent) { - SDClass_Base *p_SD = static_cast(object); - p_SD->file.open(parentDir, filePathComponent, p_SD->fileOpenMode); - if (p_SD->fileOpenMode == FILE_WRITE) { - p_SD->file.seekSet(p_SD->file.fileSize()); - } - // TODO: Return file open result? - return false; - } - return true; - } - */ + Expects the context object to be an instance of `SDClass_Base` and + will use the `file` property of the instance to open the requested + file/directory with the associated file open mode property. + Always returns true if the directory traversal hasn't reached the + bottom of the directory hierarchy. + Returns false once the file has been opened--to prevent the traversal + from descending further. (This may be unnecessary.) - bool callback_remove(SdFile& parentDir, const char *filePathComponent, - bool isLastComponent, void * /* object */) { - if (isLastComponent) { - return SdFile::remove(parentDir, filePathComponent); - } - return true; + if (isLastComponent) { + SDClass_Base *p_SD = static_cast(object); + p_SD->file.open(parentDir, filePathComponent, p_SD->fileOpenMode); + if (p_SD->fileOpenMode == FILE_WRITE) { + p_SD->file.seekSet(p_SD->file.fileSize()); } - - bool callback_rmdir(SdFile& parentDir, const char *filePathComponent, - bool isLastComponent, void * /* object */) { - if (isLastComponent) { - SdFile f; - if (!f.open(parentDir, filePathComponent, O_READ)) { - return false; - } - return f.rmDir(); - } - return true; + // TODO: Return file open result? + return false; } + return true; + } +*/ - - - /* Implementation of class used to create `SDCard` object. */ - - - - bool SDClass_Base::begin(uint8_t csPin) { - if (root.isOpen()) { - root.close(); +bool callback_remove(SdFile &parentDir, const char *filePathComponent, + bool isLastComponent, void * /* object */) { + if (isLastComponent) { + return SdFile::remove(parentDir, filePathComponent); + } + return true; +} + +bool callback_rmdir(SdFile &parentDir, const char *filePathComponent, + bool isLastComponent, void * /* object */) { + if (isLastComponent) { + SdFile f; + if (!f.open(parentDir, filePathComponent, O_READ)) { + return false; } + return f.rmDir(); + } + return true; +} - /* +/* Implementation of class used to create `SDCard` object. */ - Performs the initialisation required by the sdfatlib library. +bool SDClass_Base::begin(uint8_t csPin) { + if (root.isOpen()) { + root.close(); + } - Return true if initialization succeeds, false otherwise. + /* - */ - return card.init(SPI_HALF_SPEED, csPin) && - volume.init(card) && - root.openRoot(volume); - } + Performs the initialisation required by the sdfatlib library. - bool SDClass_Base::begin(uint32_t clock, uint8_t csPin) { - if (root.isOpen()) { - root.close(); - } + Return true if initialization succeeds, false otherwise. - return card.init(SPI_HALF_SPEED, csPin) && - card.setSpiClock(clock) && - volume.init(card) && - root.openRoot(volume); - } + */ + return card.init(SPI_HALF_SPEED, csPin) && volume.init(card) && + root.openRoot(volume); +} - //call this when a card is removed. It will allow you to insert and initialise a new card. - void SDClass_Base::end() { +bool SDClass_Base::begin(uint32_t clock, uint8_t csPin) { + if (root.isOpen()) { root.close(); } - // this little helper is used to traverse paths - SdFile SDClass_Base::getParentDir(const char *filepath, int *index) { - // get parent directory - SdFile d1; - SdFile d2; + return card.init(SPI_HALF_SPEED, csPin) && card.setSpiClock(clock) && + volume.init(card) && root.openRoot(volume); +} - d1.openRoot(volume); // start with the mostparent, root! +// call this when a card is removed. It will allow you to insert and initialise +// a new card. +void SDClass_Base::end() { root.close(); } - // we'll use the pointers to swap between the two objects - SdFile *parent = &d1; - SdFile *subdir = &d2; +// this little helper is used to traverse paths +SdFile SDClass_Base::getParentDir(const char *filepath, int *index) { + // get parent directory + SdFile d1; + SdFile d2; - const char *origpath = filepath; + d1.openRoot(volume); // start with the mostparent, root! - while (strchr(filepath, '/')) { - - // get rid of leading /'s - if (filepath[0] == '/') { - filepath++; - continue; - } + // we'll use the pointers to swap between the two objects + SdFile *parent = &d1; + SdFile *subdir = &d2; - if (! strchr(filepath, '/')) { - // it was in the root directory, so leave now - break; - } - - // extract just the name of the next subdirectory - uint8_t idx = strchr(filepath, '/') - filepath; - if (idx > 12) { - idx = 12; // don't let them specify long names - } - char subdirname[13]; - strncpy(subdirname, filepath, idx); - subdirname[idx] = 0; - - // close the subdir (we reuse them) if open - subdir->close(); - if (! subdir->open(parent, subdirname, O_READ)) { - // failed to open one of the subdirectories - return SdFile(); - } - // move forward to the next subdirectory - filepath += idx; + const char *origpath = filepath; - // we reuse the objects, close it. - parent->close(); + while (strchr(filepath, '/')) { - // swap the pointers - SdFile *t = parent; - parent = subdir; - subdir = t; + // get rid of leading /'s + if (filepath[0] == '/') { + filepath++; + continue; } - *index = (int)(filepath - origpath); - // parent is now the parent directory of the file! - return *parent; - } - + if (!strchr(filepath, '/')) { + // it was in the root directory, so leave now + break; + } - File_Base SDClass_Base::open(const char *filepath, uint8_t mode) { - /* + // extract just the name of the next subdirectory + uint8_t idx = strchr(filepath, '/') - filepath; + if (idx > 12) { + idx = 12; // don't let them specify long names + } + char subdirname[13]; + strncpy(subdirname, filepath, idx); + subdirname[idx] = 0; + + // close the subdir (we reuse them) if open + subdir->close(); + if (!subdir->open(parent, subdirname, O_READ)) { + // failed to open one of the subdirectories + return SdFile(); + } + // move forward to the next subdirectory + filepath += idx; - Open the supplied file path for reading or writing. + // we reuse the objects, close it. + parent->close(); - The file content can be accessed via the `file` property of - the `SDClass_Base` object--this property is currently - a standard `SdFile` object from `sdfatlib`. + // swap the pointers + SdFile *t = parent; + parent = subdir; + subdir = t; + } - Defaults to read only. + *index = (int)(filepath - origpath); + // parent is now the parent directory of the file! + return *parent; +} - If `write` is true, default action (when `append` is true) is to - append data to the end of the file. +File_Base SDClass_Base::open(const char *filepath, uint8_t mode) { + /* - If `append` is false then the file will be truncated first. + Open the supplied file path for reading or writing. - If the file does not exist and it is opened for writing the file - will be created. + The file content can be accessed via the `file` property of + the `SDClass_Base` object--this property is currently + a standard `SdFile` object from `sdfatlib`. - An attempt to open a file for reading that does not exist is an - error. + Defaults to read only. - */ + If `write` is true, default action (when `append` is true) is to + append data to the end of the file. - int pathidx; + If `append` is false then the file will be truncated first. - // do the interactive search - SdFile parentdir = getParentDir(filepath, &pathidx); - // no more subdirs! + If the file does not exist and it is opened for writing the file + will be created. - filepath += pathidx; + An attempt to open a file for reading that does not exist is an + error. - if (! filepath[0]) { - // it was the directory itself! - return File_Base(parentdir, "/"); - } + */ - // Open the file itself - SdFile file; + int pathidx; - // failed to open a subdir! - if (!parentdir.isOpen()) { - return File_Base(); - } + // do the interactive search + SdFile parentdir = getParentDir(filepath, &pathidx); + // no more subdirs! - if (! file.open(parentdir, filepath, mode)) { - return File_Base(); - } - // close the parent - parentdir.close(); + filepath += pathidx; - if ((mode & (O_APPEND | O_WRITE)) == (O_APPEND | O_WRITE)) { - file.seekSet(file.fileSize()); - } - return File_Base(file, filepath); + if (!filepath[0]) { + // it was the directory itself! + return File_Base(parentdir, "/"); } + // Open the file itself + SdFile file; - /* - File SDClass_Base::open(char *filepath, uint8_t mode) { - // - - Open the supplied file path for reading or writing. - - The file content can be accessed via the `file` property of - the `SDClass_Base` object--this property is currently - a standard `SdFile` object from `sdfatlib`. - - Defaults to read only. + // failed to open a subdir! + if (!parentdir.isOpen()) { + return File_Base(); + } - If `write` is true, default action (when `append` is true) is to - append data to the end of the file. + if (!file.open(parentdir, filepath, mode)) { + return File_Base(); + } + // close the parent + parentdir.close(); - If `append` is false then the file will be truncated first. + if ((mode & (O_APPEND | O_WRITE)) == (O_APPEND | O_WRITE)) { + file.seekSet(file.fileSize()); + } + return File_Base(file, filepath); +} - If the file does not exist and it is opened for writing the file - will be created. +/* + File SDClass_Base::open(char *filepath, uint8_t mode) { + // - An attempt to open a file for reading that does not exist is an - error. + Open the supplied file path for reading or writing. - // + The file content can be accessed via the `file` property of + the `SDClass_Base` object--this property is currently + a standard `SdFile` object from `sdfatlib`. - // TODO: Allow for read&write? (Possibly not, as it requires seek.) + Defaults to read only. - fileOpenMode = mode; - walkPath(filepath, root, callback_openPath, this); + If `write` is true, default action (when `append` is true) is to + append data to the end of the file. - return File_Base(); + If `append` is false then the file will be truncated first. - } - */ + If the file does not exist and it is opened for writing the file + will be created. + An attempt to open a file for reading that does not exist is an + error. - //bool SDClass_Base::close() { - // /* - // - // Closes the file opened by the `open` method. - // - // */ - // file.close(); - //} + // + // TODO: Allow for read&write? (Possibly not, as it requires seek.) - bool SDClass_Base::exists(const char *filepath) { - /* + fileOpenMode = mode; + walkPath(filepath, root, callback_openPath, this); - Returns true if the supplied file path exists. + return File_Base(); - */ - return walkPath(filepath, root, callback_pathExists); } +*/ +// bool SDClass_Base::close() { +// /* +// +// Closes the file opened by the `open` method. +// +// */ +// file.close(); +//} - //bool SDClass_Base::exists(char *filepath, SdFile& parentDir) { - // /* - // - // Returns true if the supplied file path rooted at `parentDir` - // exists. - // - // */ - // return walkPath(filepath, parentDir, callback_pathExists); - //} - - - bool SDClass_Base::mkdir(const char *filepath) { - /* +bool SDClass_Base::exists(const char *filepath) { + /* - Makes a single directory or a hierarchy of directories. + Returns true if the supplied file path exists. - A rough equivalent to `mkdir -p`. + */ + return walkPath(filepath, root, callback_pathExists); +} + +// bool SDClass_Base::exists(char *filepath, SdFile& parentDir) { +// /* +// +// Returns true if the supplied file path rooted at `parentDir` +// exists. +// +// */ +// return walkPath(filepath, parentDir, callback_pathExists); +//} + +bool SDClass_Base::mkdir(const char *filepath) { + /* - */ - return walkPath(filepath, root, callback_makeDirPath); - } + Makes a single directory or a hierarchy of directories. - bool SDClass_Base::rmdir(const char *filepath) { - /* + A rough equivalent to `mkdir -p`. - Remove a single directory or a hierarchy of directories. + */ + return walkPath(filepath, root, callback_makeDirPath); +} - A rough equivalent to `rm -rf`. +bool SDClass_Base::rmdir(const char *filepath) { + /* - */ - return walkPath(filepath, root, callback_rmdir); - } + Remove a single directory or a hierarchy of directories. - bool SDClass_Base::remove(const char *filepath) { - return walkPath(filepath, root, callback_remove); - } + A rough equivalent to `rm -rf`. + */ + return walkPath(filepath, root, callback_rmdir); +} - // allows you to recurse into a directory - File_Base File_Base::openNextFile(uint8_t mode) { - dir_t p; +bool SDClass_Base::remove(const char *filepath) { + return walkPath(filepath, root, callback_remove); +} - //Serial.print("\t\treading dir..."); - while (_file->readDir(&p) > 0) { +// allows you to recurse into a directory +File_Base File_Base::openNextFile(uint8_t mode) { + dir_t p; - // done if past last used entry - if (p.name[0] == DIR_NAME_FREE) { - //Serial.println("end"); - return File_Base(); - } + // Serial.print("\t\treading dir..."); + while (_file->readDir(&p) > 0) { - // skip deleted entry and entries for . and .. - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') { - //Serial.println("dots"); - continue; - } + // done if past last used entry + if (p.name[0] == DIR_NAME_FREE) { + // Serial.println("end"); + return File_Base(); + } - // only list subdirectories and files - if (!DIR_IS_FILE_OR_SUBDIR(&p)) { - //Serial.println("notafile"); - continue; - } + // skip deleted entry and entries for . and .. + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') { + // Serial.println("dots"); + continue; + } - // print file name with possible blank fill - SdFile f; - char name[13]; - _file->dirName(p, name); - //Serial.print("try to open file "); - //Serial.println(name); - - if (f.open(_file, name, mode)) { - //Serial.println("OK!"); - return File_Base(f, name); - } else { - //Serial.println("ugh"); - return File_Base(); - } + // only list subdirectories and files + if (!DIR_IS_FILE_OR_SUBDIR(&p)) { + // Serial.println("notafile"); + continue; } - //Serial.println("nothing"); - return File_Base(); + // print file name with possible blank fill + SdFile f; + char name[13]; + _file->dirName(p, name); + // Serial.print("try to open file "); + // Serial.println(name); + + if (f.open(_file, name, mode)) { + // Serial.println("OK!"); + return File_Base(f, name); + } else { + // Serial.println("ugh"); + return File_Base(); + } } - void File_Base::rewindDirectory(void) { - if (isDirectory()) { - _file->rewind(); - } + // Serial.println("nothing"); + return File_Base(); +} + +void File_Base::rewindDirectory(void) { + if (isDirectory()) { + _file->rewind(); } +} - SDClass_Base SD; +SDClass_Base SD; -}; +}; // namespace SDLib diff --git a/src/utility/FatStructs.h b/src/utility/FatStructs.h index 84c1cc7..2d3a05e 100644 --- a/src/utility/FatStructs.h +++ b/src/utility/FatStructs.h @@ -46,12 +46,12 @@ struct partitionTable { partition. Legal values include: 0X00. Do not use for booting. 0X80 Active partition. */ - uint8_t boot; + uint8_t boot; /** Head part of Cylinder-head-sector address of the first block in the partition. Legal values are 0-255. Only used in old PC BIOS. */ - uint8_t beginHead; + uint8_t beginHead; /** Sector part of Cylinder-head-sector address of the first block in the partition. Legal values are 1-63. Only used in old PC BIOS. @@ -63,17 +63,17 @@ struct partitionTable { Combine beginCylinderLow with beginCylinderHigh. Legal values are 0-1023. Only used in old PC BIOS. */ - uint8_t beginCylinderLow; + uint8_t beginCylinderLow; /** Partition type. See defines that begin with PART_TYPE_ for some Microsoft partition types. */ - uint8_t type; + uint8_t type; /** head part of cylinder-head-sector address of the last sector in the partition. Legal values are 0-255. Only used in old PC BIOS. */ - uint8_t endHead; + uint8_t endHead; /** Sector part of cylinder-head-sector address of the last sector in the partition. Legal values are 1-63. Only used in old PC BIOS. @@ -85,7 +85,7 @@ struct partitionTable { Combine endCylinderLow with endCylinderHigh. Legal values are 0-1023. Only used in old PC BIOS. */ - uint8_t endCylinderLow; + uint8_t endCylinderLow; /** Logical block address of the first block in the partition. */ uint32_t firstSector; /** Length of the partition, in blocks. */ @@ -103,17 +103,17 @@ typedef struct partitionTable part_t; */ struct masterBootRecord { /** Code Area for master boot program. */ - uint8_t codeArea[440]; + uint8_t codeArea[440]; /** Optional WindowsNT disk signature. May contain more boot code. */ uint32_t diskSignature; /** Usually zero but may be more boot code. */ uint16_t usuallyZero; /** Partition tables. */ - part_t part[4]; + part_t part[4]; /** First MBR signature byte. Must be 0X55 */ - uint8_t mbrSig0; + uint8_t mbrSig0; /** Second MBR signature byte. Must be 0XAA */ - uint8_t mbrSig1; + uint8_t mbrSig1; } __attribute__((packed)); /** Type name for masterBootRecord */ typedef struct masterBootRecord mbr_t; @@ -136,7 +136,7 @@ struct biosParmBlock { power of 2 that is greater than 0. The legal values are 1, 2, 4, 8, 16, 32, 64, and 128. */ - uint8_t sectorsPerCluster; + uint8_t sectorsPerCluster; /** Number of sectors before the first FAT. This value must not be zero. @@ -145,7 +145,7 @@ struct biosParmBlock { /** The count of FAT data structures on the volume. This field should always contain the value 2 for any FAT volume of any type. */ - uint8_t fatCount; + uint8_t fatCount; /** For FAT12 and FAT16 volumes, this field contains the count of 32-byte directory entries in the root directory. For FAT32 volumes, @@ -171,7 +171,7 @@ struct biosParmBlock { for fixed (non-removable) media. For removable media, 0xF0 is frequently used. Legal values are 0xF0 or 0xF8-0xFF. */ - uint8_t mediaType; + uint8_t mediaType; /** Count of sectors occupied by one FAT on FAT12/FAT16 volumes. On FAT32 volumes this field must be 0, and sectorsPerFat32 @@ -206,8 +206,8 @@ struct biosParmBlock { Only valid if mirroring is disabled. Bits 4-6 -- Reserved. Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. - -- 1 means only one FAT is active; it is the one referenced in bits 0-3. - Bits 8-15 -- Reserved. + -- 1 means only one FAT is active; it is the one referenced in bits + 0-3. Bits 8-15 -- Reserved. */ uint16_t fat32Flags; /** @@ -235,7 +235,7 @@ struct biosParmBlock { Reserved for future expansion. Code that formats FAT32 volumes should always set all of the bytes of this field to 0. */ - uint8_t fat32Reserved[12]; + uint8_t fat32Reserved[12]; } __attribute__((packed)); /** Type name for biosParmBlock */ typedef struct biosParmBlock bpb_t; @@ -248,29 +248,29 @@ typedef struct biosParmBlock bpb_t; */ struct fat32BootSector { /** X86 jmp to boot program */ - uint8_t jmpToBootCode[3]; + uint8_t jmpToBootCode[3]; /** informational only - don't depend on it */ - char oemName[8]; + char oemName[8]; /** BIOS Parameter Block */ - bpb_t bpb; + bpb_t bpb; /** for int0x13 use value 0X80 for hard drive */ - uint8_t driveNumber; + uint8_t driveNumber; /** used by Windows NT - should be zero for FAT */ - uint8_t reserved1; + uint8_t reserved1; /** 0X29 if next three fields are valid */ - uint8_t bootSignature; + uint8_t bootSignature; /** usually generated by combining date and time */ uint32_t volumeSerialNumber; /** should match volume label in root dir */ - char volumeLabel[11]; + char volumeLabel[11]; /** informational only - don't depend on it */ - char fileSystemType[8]; + char fileSystemType[8]; /** X86 boot code */ - uint8_t bootCode[420]; + uint8_t bootCode[420]; /** must be 0X55 */ - uint8_t bootSectorSig0; + uint8_t bootSectorSig0; /** must be 0XAA */ - uint8_t bootSectorSig1; + uint8_t bootSectorSig1; } __attribute__((packed)); //------------------------------------------------------------------------------ // End Of Chain values for FAT entries @@ -324,25 +324,25 @@ struct directoryEntry { The first eight bytes contain the file name with blank fill. The last three bytes contain the file extension with blank fill. */ - uint8_t name[11]; + uint8_t name[11]; /** Entry attributes. The upper two bits of the attribute byte are reserved and should always be set to 0 when a file is created and never modified or looked at after that. See defines that begin with DIR_ATT_. */ - uint8_t attributes; + uint8_t attributes; /** Reserved for use by Windows NT. Set value to 0 when a file is created and never modify or look at it after that. */ - uint8_t reservedNT; + uint8_t reservedNT; /** The granularity of the seconds part of creationTime is 2 seconds so this field is a count of tenths of a second and its valid value range is 0-199 inclusive. (WHG note - seems to be hundredths) */ - uint8_t creationTimeTenths; + uint8_t creationTimeTenths; /** Time file was created. */ uint16_t creationTime; /** Date file was created. */ @@ -398,21 +398,21 @@ uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; /** defined attribute bits */ uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; /** Directory entry is part of a long name */ -static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { +static inline uint8_t DIR_IS_LONG_NAME(const dir_t *dir) { return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; } /** Mask for file/subdirectory tests */ uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); /** Directory entry is for a file */ -static inline uint8_t DIR_IS_FILE(const dir_t* dir) { +static inline uint8_t DIR_IS_FILE(const dir_t *dir) { return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; } /** Directory entry is for a subdirectory */ -static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { +static inline uint8_t DIR_IS_SUBDIR(const dir_t *dir) { return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; } /** Directory entry is for a file or subdirectory */ -static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { +static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t *dir) { return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; } -#endif // FatStructs_h +#endif // FatStructs_h diff --git a/src/utility/Sd2Card.cpp b/src/utility/Sd2Card.cpp index 7cfbe73..b244ae8 100644 --- a/src/utility/Sd2Card.cpp +++ b/src/utility/Sd2Card.cpp @@ -18,43 +18,44 @@ . */ #define USE_SPI_LIB -#include #include "Sd2Card.h" +#include + //------------------------------------------------------------------------------ #ifndef SOFTWARE_SPI #ifdef USE_SPI_LIB - #ifndef SDCARD_SPI - #define SDCARD_SPI SPI - #endif +#ifndef SDCARD_SPI +#define SDCARD_SPI SPI +#endif - #include - static SPISettings settings; +#include +static SPISettings settings; #endif // functions for hardware SPI /** Send a byte to the card */ static void spiSend(uint8_t b) { - #ifndef USE_SPI_LIB +#ifndef USE_SPI_LIB SPDR = b; while (!(SPSR & (1 << SPIF))) ; - #else +#else SDCARD_SPI.transfer(b); - #endif +#endif } /** Receive a byte from the card */ -static uint8_t spiRec(void) { - #ifndef USE_SPI_LIB +static uint8_t spiRec(void) { +#ifndef USE_SPI_LIB spiSend(0XFF); return SPDR; - #else +#else return SDCARD_SPI.transfer(0xFF); - #endif +#endif } -#else // SOFTWARE_SPI +#else // SOFTWARE_SPI //------------------------------------------------------------------------------ /** nop to tune soft SPI timing */ -#define nop asm volatile ("nop\n\t") +#define nop asm volatile("nop\n\t") //------------------------------------------------------------------------------ /** Soft SPI receive */ uint8_t spiRec(void) { @@ -107,7 +108,7 @@ void spiSend(uint8_t data) { // enable interrupts sei(); } -#endif // SOFTWARE_SPI +#endif // SOFTWARE_SPI //------------------------------------------------------------------------------ // send command and return error code. Return zero for OK uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { @@ -131,10 +132,10 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { // send CRC uint8_t crc = 0XFF; if (cmd == CMD0) { - crc = 0X95; // correct crc for CMD0 with arg 0 + crc = 0X95; // correct crc for CMD0 with arg 0 } if (cmd == CMD8) { - crc = 0X87; // correct crc for CMD8 with arg 0X1AA + crc = 0X87; // correct crc for CMD8 with arg 0X1AA } spiSend(crc); @@ -157,14 +158,14 @@ uint32_t Sd2Card::cardSize(void) { } if (csd.v1.csd_ver == 0) { uint8_t read_bl_len = csd.v1.read_bl_len; - uint16_t c_size = (csd.v1.c_size_high << 10) - | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; - uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) - | csd.v1.c_size_mult_low; + uint16_t c_size = (csd.v1.c_size_high << 10) | (csd.v1.c_size_mid << 2) | + csd.v1.c_size_low; + uint8_t c_size_mult = + (csd.v1.c_size_mult_high << 1) | csd.v1.c_size_mult_low; return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); } else if (csd.v2.csd_ver == 1) { - uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) - | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; + uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) | + (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; return (c_size + 1) << 10; } else { error(SD_CARD_ERROR_BAD_CSD); @@ -176,21 +177,21 @@ static uint8_t chip_select_asserted = 0; void Sd2Card::chipSelectHigh(void) { digitalWrite(chipSelectPin_, HIGH); - #ifdef USE_SPI_LIB +#ifdef USE_SPI_LIB if (chip_select_asserted) { chip_select_asserted = 0; SDCARD_SPI.endTransaction(); } - #endif +#endif } //------------------------------------------------------------------------------ void Sd2Card::chipSelectLow(void) { - #ifdef USE_SPI_LIB +#ifdef USE_SPI_LIB if (!chip_select_asserted) { chip_select_asserted = 1; SDCARD_SPI.beginTransaction(settings); } - #endif +#endif digitalWrite(chipSelectPin_, LOW); } //------------------------------------------------------------------------------ @@ -216,9 +217,8 @@ uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { firstBlock <<= 9; lastBlock <<= 9; } - if (cardCommand(CMD32, firstBlock) - || cardCommand(CMD33, lastBlock) - || cardCommand(CMD38, 0)) { + if (cardCommand(CMD32, firstBlock) || cardCommand(CMD33, lastBlock) || + cardCommand(CMD38, 0)) { error(SD_CARD_ERROR_ERASE); goto fail; } @@ -264,14 +264,14 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { // set pin modes pinMode(chipSelectPin_, OUTPUT); digitalWrite(chipSelectPin_, HIGH); - #ifndef USE_SPI_LIB +#ifndef USE_SPI_LIB pinMode(SPI_MISO_PIN, INPUT); pinMode(SPI_MOSI_PIN, OUTPUT); pinMode(SPI_SCK_PIN, OUTPUT); - #endif +#endif - #ifndef SOFTWARE_SPI - #ifndef USE_SPI_LIB +#ifndef SOFTWARE_SPI +#ifndef USE_SPI_LIB // SS must be in output mode even it is not chip select pinMode(SS_PIN, OUTPUT); digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin @@ -279,22 +279,22 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // clear double speed SPSR &= ~(1 << SPI2X); - #else // USE_SPI_LIB +#else // USE_SPI_LIB SDCARD_SPI.begin(); settings = SPISettings(250000, MSBFIRST, SPI_MODE0); - #endif // USE_SPI_LIB - #endif // SOFTWARE_SPI +#endif // USE_SPI_LIB +#endif // SOFTWARE_SPI - // must supply min of 74 clock cycles with CS high. - #ifdef USE_SPI_LIB +// must supply min of 74 clock cycles with CS high. +#ifdef USE_SPI_LIB SDCARD_SPI.beginTransaction(settings); - #endif +#endif for (uint8_t i = 0; i < 10; i++) { spiSend(0XFF); } - #ifdef USE_SPI_LIB +#ifdef USE_SPI_LIB SDCARD_SPI.endTransaction(); - #endif +#endif chipSelectLow(); @@ -347,11 +347,11 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { } chipSelectHigh(); - #ifndef SOFTWARE_SPI +#ifndef SOFTWARE_SPI return setSckRate(sckRateID); - #else // SOFTWARE_SPI +#else // SOFTWARE_SPI return true; - #endif // SOFTWARE_SPI +#endif // SOFTWARE_SPI fail: chipSelectHigh(); @@ -385,7 +385,7 @@ void Sd2Card::partialBlockRead(uint8_t value) { \return The value one, true, is returned for success and the value zero, false, is returned for failure. */ -uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { +uint8_t Sd2Card::readBlock(uint32_t block, uint8_t *dst) { return readData(block, 0, 512, dst); } //------------------------------------------------------------------------------ @@ -399,8 +399,8 @@ uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { \return The value one, true, is returned for success and the value zero, false, is returned for failure. */ -uint8_t Sd2Card::readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst) { +uint8_t Sd2Card::readData(uint32_t block, uint16_t offset, uint16_t count, + uint8_t *dst) { if (count == 0) { return true; } @@ -424,7 +424,7 @@ uint8_t Sd2Card::readData(uint32_t block, inBlock_ = 1; } - #ifdef OPTIMIZE_HARDWARE_SPI +#ifdef OPTIMIZE_HARDWARE_SPI // start first spi transfer SPDR = 0XFF; @@ -447,7 +447,7 @@ uint8_t Sd2Card::readData(uint32_t block, ; dst[n] = SPDR; - #else // OPTIMIZE_HARDWARE_SPI +#else // OPTIMIZE_HARDWARE_SPI // skip data before offset for (; offset_ < offset; offset_++) { @@ -457,7 +457,7 @@ uint8_t Sd2Card::readData(uint32_t block, for (uint16_t i = 0; i < count; i++) { dst[i] = spiRec(); } - #endif // OPTIMIZE_HARDWARE_SPI +#endif // OPTIMIZE_HARDWARE_SPI offset_ += count; if (!partialBlockRead_ || offset_ >= 512) { @@ -474,8 +474,8 @@ uint8_t Sd2Card::readData(uint32_t block, /** Skip remaining data in a block when in partial block read mode. */ void Sd2Card::readEnd(void) { if (inBlock_) { - // skip data and crc - #ifdef OPTIMIZE_HARDWARE_SPI +// skip data and crc +#ifdef OPTIMIZE_HARDWARE_SPI // optimize skip for hardware SPDR = 0XFF; while (offset_++ < 513) { @@ -486,19 +486,19 @@ void Sd2Card::readEnd(void) { // wait for last crc byte while (!(SPSR & (1 << SPIF))) ; - #else // OPTIMIZE_HARDWARE_SPI +#else // OPTIMIZE_HARDWARE_SPI while (offset_++ < 514) { spiRec(); } - #endif // OPTIMIZE_HARDWARE_SPI +#endif // OPTIMIZE_HARDWARE_SPI chipSelectHigh(); inBlock_ = 0; } } //------------------------------------------------------------------------------ /** read CID or CSR register */ -uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { - uint8_t* dst = reinterpret_cast(buf); +uint8_t Sd2Card::readRegister(uint8_t cmd, void *buf) { + uint8_t *dst = reinterpret_cast(buf); if (cardCommand(cmd, 0)) { error(SD_CARD_ERROR_READ_REG); goto fail; @@ -510,8 +510,8 @@ uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { for (uint16_t i = 0; i < 16; i++) { dst[i] = spiRec(); } - spiRec(); // get first crc byte - spiRec(); // get second crc byte + spiRec(); // get first crc byte + spiRec(); // get second crc byte chipSelectHigh(); return true; @@ -537,7 +537,7 @@ uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { error(SD_CARD_ERROR_SCK_RATE); return false; } - #ifndef USE_SPI_LIB +#ifndef USE_SPI_LIB // see avr processor datasheet for SPI register bit definitions if ((sckRateID & 1) || sckRateID == 6) { SPSR &= ~(1 << SPI2X); @@ -545,19 +545,31 @@ uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { SPSR |= (1 << SPI2X); } SPCR &= ~((1 << SPR1) | (1 << SPR0)); - SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0) - | (sckRateID & 2 ? (1 << SPR0) : 0); - #else // USE_SPI_LIB + SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0) | (sckRateID & 2 ? (1 << SPR0) : 0); +#else // USE_SPI_LIB switch (sckRateID) { - case 0: settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); break; - case 1: settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); break; - case 2: settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); break; - case 3: settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); break; - case 4: settings = SPISettings(500000, MSBFIRST, SPI_MODE0); break; - case 5: settings = SPISettings(250000, MSBFIRST, SPI_MODE0); break; - default: settings = SPISettings(125000, MSBFIRST, SPI_MODE0); - } - #endif // USE_SPI_LIB + case 0: + settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); + break; + case 1: + settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); + break; + case 2: + settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); + break; + case 3: + settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); + break; + case 4: + settings = SPISettings(500000, MSBFIRST, SPI_MODE0); + break; + case 5: + settings = SPISettings(250000, MSBFIRST, SPI_MODE0); + break; + default: + settings = SPISettings(125000, MSBFIRST, SPI_MODE0); + } +#endif // USE_SPI_LIB return true; } #ifdef USE_SPI_LIB @@ -612,14 +624,15 @@ uint8_t Sd2Card::waitStartBlock(void) { \return The value one, true, is returned for success and the value zero, false, is returned for failure. */ -uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking) { - #if SD_PROTECT_BLOCK_ZERO +uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t *src, + uint8_t blocking) { +#if SD_PROTECT_BLOCK_ZERO // don't allow write to first block if (blockNumber == 0) { error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); goto fail; } - #endif // SD_PROTECT_BLOCK_ZERO +#endif // SD_PROTECT_BLOCK_ZERO // use address if not SDHC card if (type() != SD_CARD_TYPE_SDHC) { @@ -653,7 +666,7 @@ uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t bl } //------------------------------------------------------------------------------ /** Write one data block in a multiple block write sequence */ -uint8_t Sd2Card::writeData(const uint8_t* src) { +uint8_t Sd2Card::writeData(const uint8_t *src) { // wait for previous write to finish if (!waitNotBusy(SD_WRITE_TIMEOUT)) { error(SD_CARD_ERROR_WRITE_MULTIPLE); @@ -664,8 +677,8 @@ uint8_t Sd2Card::writeData(const uint8_t* src) { } //------------------------------------------------------------------------------ // send one block of data for write block or write multiple blocks -uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { - #ifdef OPTIMIZE_HARDWARE_SPI +uint8_t Sd2Card::writeData(uint8_t token, const uint8_t *src) { +#ifdef OPTIMIZE_HARDWARE_SPI // send data - optimized loop SPDR = token; @@ -684,14 +697,14 @@ uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { while (!(SPSR & (1 << SPIF))) ; - #else // OPTIMIZE_HARDWARE_SPI +#else // OPTIMIZE_HARDWARE_SPI spiSend(token); for (uint16_t i = 0; i < 512; i++) { spiSend(src[i]); } - #endif // OPTIMIZE_HARDWARE_SPI - spiSend(0xff); // dummy crc - spiSend(0xff); // dummy crc +#endif // OPTIMIZE_HARDWARE_SPI + spiSend(0xff); // dummy crc + spiSend(0xff); // dummy crc status_ = spiRec(); if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { @@ -714,13 +727,13 @@ uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { the value zero, false, is returned for failure. */ uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { - #if SD_PROTECT_BLOCK_ZERO +#if SD_PROTECT_BLOCK_ZERO // don't allow write to first block if (blockNumber == 0) { error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); goto fail; } - #endif // SD_PROTECT_BLOCK_ZERO +#endif // SD_PROTECT_BLOCK_ZERO // send pre-erase count if (cardAcmd(ACMD23, eraseCount)) { error(SD_CARD_ERROR_ACMD23); diff --git a/src/utility/Sd2Card.h b/src/utility/Sd2Card.h index cb55ff4..bf8d60b 100644 --- a/src/utility/Sd2Card.h +++ b/src/utility/Sd2Card.h @@ -46,69 +46,71 @@ uint8_t const SPI_QUARTER_SPEED = 2; */ #define MEGA_SOFT_SPI 0 //------------------------------------------------------------------------------ -#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) - #define SOFTWARE_SPI -#endif // MEGA_SOFT_SPI +#if MEGA_SOFT_SPI && \ + (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) +#define SOFTWARE_SPI +#endif // MEGA_SOFT_SPI //------------------------------------------------------------------------------ // SPI pin definitions // #ifndef SOFTWARE_SPI - // hardware pin defs +// hardware pin defs - // include pins_arduino.h or variant.h depending on architecture, via Arduino.h - #include - #if defined(MOCK_PINS_COUNT) & !defined(SDCARD_SS_PIN) - #define SDCARD_SS_PIN 4 - #define SDCARD_MOSI_PIN 11 - #define SDCARD_MISO_PIN 12 - #define SDCARD_SCK_PIN 13 - #endif +// include pins_arduino.h or variant.h depending on architecture, via Arduino.h +#include +#if defined(MOCK_PINS_COUNT) & !defined(SDCARD_SS_PIN) +#define SDCARD_SS_PIN 4 +#define SDCARD_MOSI_PIN 11 +#define SDCARD_MISO_PIN 12 +#define SDCARD_SCK_PIN 13 +#endif - /** - SD Chip Select pin +/** +SD Chip Select pin - Warning if this pin is redefined the hardware SS will pin will be enabled - as an output by init(). An avr processor will not function as an SPI - master unless SS is set to output mode. - */ - #ifndef SDCARD_SS_PIN - /** The default chip select pin for the SD card is SS. */ - uint8_t const SD_CHIP_SELECT_PIN = SS; - #else - uint8_t const SD_CHIP_SELECT_PIN = SDCARD_SS_PIN; - #endif +Warning if this pin is redefined the hardware SS will pin will be enabled +as an output by init(). An avr processor will not function as an SPI +master unless SS is set to output mode. +*/ +#ifndef SDCARD_SS_PIN +/** The default chip select pin for the SD card is SS. */ +uint8_t const SD_CHIP_SELECT_PIN = SS; +#else +uint8_t const SD_CHIP_SELECT_PIN = SDCARD_SS_PIN; +#endif - // The following three pins must not be redefined for hardware SPI, - // so ensure that they are taken from pins_arduino.h or variant.h, depending on architecture. - #ifndef SDCARD_MOSI_PIN - /** SPI Master Out Slave In pin */ - uint8_t const SPI_MOSI_PIN = MOSI; - /** SPI Master In Slave Out pin */ - uint8_t const SPI_MISO_PIN = MISO; - /** SPI Clock pin */ - uint8_t const SPI_SCK_PIN = SCK; - #else - uint8_t const SPI_MOSI_PIN = SDCARD_MOSI_PIN; - uint8_t const SPI_MISO_PIN = SDCARD_MISO_PIN; - uint8_t const SPI_SCK_PIN = SDCARD_SCK_PIN; - #endif +// The following three pins must not be redefined for hardware SPI, +// so ensure that they are taken from pins_arduino.h or variant.h, depending on +// architecture. +#ifndef SDCARD_MOSI_PIN +/** SPI Master Out Slave In pin */ +uint8_t const SPI_MOSI_PIN = MOSI; +/** SPI Master In Slave Out pin */ +uint8_t const SPI_MISO_PIN = MISO; +/** SPI Clock pin */ +uint8_t const SPI_SCK_PIN = SCK; +#else +uint8_t const SPI_MOSI_PIN = SDCARD_MOSI_PIN; +uint8_t const SPI_MISO_PIN = SDCARD_MISO_PIN; +uint8_t const SPI_SCK_PIN = SDCARD_SCK_PIN; +#endif - /** optimize loops for hardware SPI */ - #ifndef USE_SPI_LIB - #define OPTIMIZE_HARDWARE_SPI - #endif +/** optimize loops for hardware SPI */ +#ifndef USE_SPI_LIB +#define OPTIMIZE_HARDWARE_SPI +#endif #else // SOFTWARE_SPI - // define software SPI pins so Mega can use unmodified GPS Shield - /** SPI chip select pin */ - uint8_t const SD_CHIP_SELECT_PIN = 10; - /** SPI Master Out Slave In pin */ - uint8_t const SPI_MOSI_PIN = 11; - /** SPI Master In Slave Out pin */ - uint8_t const SPI_MISO_PIN = 12; - /** SPI Clock pin */ - uint8_t const SPI_SCK_PIN = 13; -#endif // SOFTWARE_SPI +// define software SPI pins so Mega can use unmodified GPS Shield +/** SPI chip select pin */ +uint8_t const SD_CHIP_SELECT_PIN = 10; +/** SPI Master Out Slave In pin */ +uint8_t const SPI_MOSI_PIN = 11; +/** SPI Master In Slave Out pin */ +uint8_t const SPI_MISO_PIN = 12; +/** SPI Clock pin */ +uint8_t const SPI_SCK_PIN = 13; +#endif // SOFTWARE_SPI //------------------------------------------------------------------------------ /** Protect block zero from write if nonzero */ #define SD_PROTECT_BLOCK_ZERO 1 @@ -180,100 +182,84 @@ uint8_t const SD_CARD_TYPE_SDHC = 3; \brief Raw access to SD and SDHC flash memory cards. */ class Sd2Card { - public: - /** Construct an instance of Sd2Card. */ - Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} - uint32_t cardSize(void); - uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); - uint8_t eraseSingleBlockEnable(void); - /** - \return error code for last error. See Sd2Card.h for a list of error codes. - */ - uint8_t errorCode(void) const { - return errorCode_; - } - /** \return error data for last error. */ - uint8_t errorData(void) const { - return status_; - } - /** - Initialize an SD flash memory card with default clock rate and chip - select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). - */ - uint8_t init(void) { - return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); - } - /** - Initialize an SD flash memory card with the selected SPI clock rate - and the default SD chip select pin. - See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). - */ - uint8_t init(uint8_t sckRateID) { - return init(sckRateID, SD_CHIP_SELECT_PIN); - } - uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); - void partialBlockRead(uint8_t value); - /** Returns the current value, true or false, for partial block read. */ - uint8_t partialBlockRead(void) const { - return partialBlockRead_; - } - uint8_t readBlock(uint32_t block, uint8_t* dst); - uint8_t readData(uint32_t block, - uint16_t offset, uint16_t count, uint8_t* dst); - /** - Read a cards CID register. The CID contains card identification - information such as Manufacturer ID, Product name, Product serial - number and Manufacturing date. */ - uint8_t readCID(cid_t* cid) { - return readRegister(CMD10, cid); - } - /** - Read a cards CSD register. The CSD contains Card-Specific Data that - provides information regarding access to the card's contents. */ - uint8_t readCSD(csd_t* csd) { - return readRegister(CMD9, csd); - } - void readEnd(void); - uint8_t setSckRate(uint8_t sckRateID); - #ifdef USE_SPI_LIB - uint8_t setSpiClock(uint32_t clock); - #endif - /** Return the card type: SD V1, SD V2 or SDHC */ - uint8_t type(void) const { - return type_; - } - uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking = 1); - uint8_t writeData(const uint8_t* src); - uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); - uint8_t writeStop(void); - uint8_t isBusy(void); - private: - uint32_t block_; - uint8_t chipSelectPin_; - uint8_t errorCode_; - uint8_t inBlock_; - uint16_t offset_; - uint8_t partialBlockRead_; - uint8_t status_; - uint8_t type_; - // private functions - uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { - cardCommand(CMD55, 0); - return cardCommand(cmd, arg); - } - uint8_t cardCommand(uint8_t cmd, uint32_t arg); - void error(uint8_t code) { - errorCode_ = code; - } - uint8_t readRegister(uint8_t cmd, void* buf); - uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); - void chipSelectHigh(void); - void chipSelectLow(void); - void type(uint8_t value) { - type_ = value; - } - uint8_t waitNotBusy(unsigned int timeoutMillis); - uint8_t writeData(uint8_t token, const uint8_t* src); - uint8_t waitStartBlock(void); +public: + /** Construct an instance of Sd2Card. */ + Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} + uint32_t cardSize(void); + uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); + uint8_t eraseSingleBlockEnable(void); + /** + \return error code for last error. See Sd2Card.h for a list of error codes. + */ + uint8_t errorCode(void) const { return errorCode_; } + /** \return error data for last error. */ + uint8_t errorData(void) const { return status_; } + /** + Initialize an SD flash memory card with default clock rate and chip + select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + */ + uint8_t init(void) { return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); } + /** + Initialize an SD flash memory card with the selected SPI clock rate + and the default SD chip select pin. + See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + */ + uint8_t init(uint8_t sckRateID) { + return init(sckRateID, SD_CHIP_SELECT_PIN); + } + uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); + void partialBlockRead(uint8_t value); + /** Returns the current value, true or false, for partial block read. */ + uint8_t partialBlockRead(void) const { return partialBlockRead_; } + uint8_t readBlock(uint32_t block, uint8_t *dst); + uint8_t readData(uint32_t block, uint16_t offset, uint16_t count, + uint8_t *dst); + /** + Read a cards CID register. The CID contains card identification + information such as Manufacturer ID, Product name, Product serial + number and Manufacturing date. */ + uint8_t readCID(cid_t *cid) { return readRegister(CMD10, cid); } + /** + Read a cards CSD register. The CSD contains Card-Specific Data that + provides information regarding access to the card's contents. */ + uint8_t readCSD(csd_t *csd) { return readRegister(CMD9, csd); } + void readEnd(void); + uint8_t setSckRate(uint8_t sckRateID); +#ifdef USE_SPI_LIB + uint8_t setSpiClock(uint32_t clock); +#endif + /** Return the card type: SD V1, SD V2 or SDHC */ + uint8_t type(void) const { return type_; } + uint8_t writeBlock(uint32_t blockNumber, const uint8_t *src, + uint8_t blocking = 1); + uint8_t writeData(const uint8_t *src); + uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); + uint8_t writeStop(void); + uint8_t isBusy(void); + +private: + uint32_t block_; + uint8_t chipSelectPin_; + uint8_t errorCode_; + uint8_t inBlock_; + uint16_t offset_; + uint8_t partialBlockRead_; + uint8_t status_; + uint8_t type_; + // private functions + uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { + cardCommand(CMD55, 0); + return cardCommand(cmd, arg); + } + uint8_t cardCommand(uint8_t cmd, uint32_t arg); + void error(uint8_t code) { errorCode_ = code; } + uint8_t readRegister(uint8_t cmd, void *buf); + uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); + void chipSelectHigh(void); + void chipSelectLow(void); + void type(uint8_t value) { type_ = value; } + uint8_t waitNotBusy(unsigned int timeoutMillis); + uint8_t writeData(uint8_t token, const uint8_t *src); + uint8_t waitStartBlock(void); }; -#endif // Sd2Card_h +#endif // Sd2Card_h diff --git a/src/utility/Sd2PinMap.cpp b/src/utility/Sd2PinMap.cpp index e247e91..9a27a49 100644 --- a/src/utility/Sd2PinMap.cpp +++ b/src/utility/Sd2PinMap.cpp @@ -1,7 +1,7 @@ #ifdef MOCK_PINS_COUNT -#include #include "Sd2PinMap.h" +#include uint8_t avr_io_registers[RAMSTART]; diff --git a/src/utility/Sd2PinMap.h b/src/utility/Sd2PinMap.h index af261f4..de6df23 100644 --- a/src/utility/Sd2PinMap.h +++ b/src/utility/Sd2PinMap.h @@ -21,54 +21,54 @@ #if defined(__arm__) // Arduino Due Board follows #ifndef Sd2PinMap_h - #define Sd2PinMap_h - - #include - #if defined(MOCK_PINS_COUNT) & !defined(SDCARD_SS_PIN) - #include - // #ifdef _SFR_IO8 - // #undef _SFR_IO8 - // #define _AVR_IO_REG(type, mem_addr) (*(type*)(&avr_io_registers[mem_addr])) - // #define __SFR_OFFSET 0x20 - // #define _SFR_IO8(io_addr) _AVR_IO_REG(uint8_t, io_addr + __SFR_OFFSET) - // #define _SFR_IO16(io_addr) _AVR_IO_REG(uint16_t, io_addr + __SFR_OFFSET) - // #define _SFR_MEM8(mem_addr) _AVR_IO_REG(uint8_t, mem_addr) - // #define _SFR_MEM16(mem_addr) _AVR_IO_REG(uint16_t, mem_addr) - // #define _SFR_MEM32(mem_addr) _AVR_IO_REG(uint32_t, mem_addr) - - // extern uint8_t avr_io_registers[RAMSTART]; - // #endif - #define SDCARD_SS_PIN 4 - #define SDCARD_MOSI_PIN 11 - #define SDCARD_MISO_PIN 12 - #define SDCARD_SCK_PIN 13 - #endif - - uint8_t const SS_PIN = SS; - uint8_t const MOSI_PIN = MOSI; - uint8_t const MISO_PIN = MISO; - uint8_t const SCK_PIN = SCK; +#define Sd2PinMap_h + +#include +#if defined(MOCK_PINS_COUNT) & !defined(SDCARD_SS_PIN) +#include +// #ifdef _SFR_IO8 +// #undef _SFR_IO8 +// #define _AVR_IO_REG(type, mem_addr) (*(type*)(&avr_io_registers[mem_addr])) +// #define __SFR_OFFSET 0x20 +// #define _SFR_IO8(io_addr) _AVR_IO_REG(uint8_t, io_addr + __SFR_OFFSET) +// #define _SFR_IO16(io_addr) _AVR_IO_REG(uint16_t, io_addr + __SFR_OFFSET) +// #define _SFR_MEM8(mem_addr) _AVR_IO_REG(uint8_t, mem_addr) +// #define _SFR_MEM16(mem_addr) _AVR_IO_REG(uint16_t, mem_addr) +// #define _SFR_MEM32(mem_addr) _AVR_IO_REG(uint32_t, mem_addr) + +// extern uint8_t avr_io_registers[RAMSTART]; +// #endif +#define SDCARD_SS_PIN 4 +#define SDCARD_MOSI_PIN 11 +#define SDCARD_MISO_PIN 12 +#define SDCARD_SCK_PIN 13 +#endif + +uint8_t const SS_PIN = SS; +uint8_t const MOSI_PIN = MOSI; +uint8_t const MISO_PIN = MISO; +uint8_t const SCK_PIN = SCK; #endif // Sd2PinMap_h #elif defined(__AVR_ATmega4809__) // Arduino UNO WiFI Rev2 follows #ifndef Sd2PinMap_h - #define Sd2PinMap_h +#define Sd2PinMap_h - #include +#include - #if defined(MOCK_PINS_COUNT) & !defined(SDCARD_SS_PIN) - #define SDCARD_SS_PIN 4 - #define SDCARD_MOSI_PIN 11 - #define SDCARD_MISO_PIN 12 - #define SDCARD_SCK_PIN 13 - #endif +#if defined(MOCK_PINS_COUNT) & !defined(SDCARD_SS_PIN) +#define SDCARD_SS_PIN 4 +#define SDCARD_MOSI_PIN 11 +#define SDCARD_MISO_PIN 12 +#define SDCARD_SCK_PIN 13 +#endif - uint8_t const SS_PIN = SS; - uint8_t const MOSI_PIN = MOSI; - uint8_t const MISO_PIN = MISO; - uint8_t const SCK_PIN = SCK; +uint8_t const SS_PIN = SS; +uint8_t const MOSI_PIN = MOSI; +uint8_t const MISO_PIN = MISO; +uint8_t const SCK_PIN = SCK; #endif // Sd2PinMap_h @@ -82,9 +82,9 @@ //------------------------------------------------------------------------------ /** struct for mapping digital pins */ struct pin_map_t { - volatile uint8_t* ddr; - volatile uint8_t* pin; - volatile uint8_t* port; + volatile uint8_t *ddr; + volatile uint8_t *pin; + volatile uint8_t *port; uint8_t bit; }; //------------------------------------------------------------------------------ @@ -102,79 +102,80 @@ uint8_t const MISO_PIN = 50; uint8_t const SCK_PIN = 52; static const pin_map_t digitalPinMap[] = { - {&DDRE, &PINE, &PORTE, 0}, // E0 0 - {&DDRE, &PINE, &PORTE, 1}, // E1 1 - {&DDRE, &PINE, &PORTE, 4}, // E4 2 - {&DDRE, &PINE, &PORTE, 5}, // E5 3 - {&DDRG, &PING, &PORTG, 5}, // G5 4 - {&DDRE, &PINE, &PORTE, 3}, // E3 5 - {&DDRH, &PINH, &PORTH, 3}, // H3 6 - {&DDRH, &PINH, &PORTH, 4}, // H4 7 - {&DDRH, &PINH, &PORTH, 5}, // H5 8 - {&DDRH, &PINH, &PORTH, 6}, // H6 9 - {&DDRB, &PINB, &PORTB, 4}, // B4 10 - {&DDRB, &PINB, &PORTB, 5}, // B5 11 - {&DDRB, &PINB, &PORTB, 6}, // B6 12 - {&DDRB, &PINB, &PORTB, 7}, // B7 13 - {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 - {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 - {&DDRH, &PINH, &PORTH, 1}, // H1 16 - {&DDRH, &PINH, &PORTH, 0}, // H0 17 - {&DDRD, &PIND, &PORTD, 3}, // D3 18 - {&DDRD, &PIND, &PORTD, 2}, // D2 19 - {&DDRD, &PIND, &PORTD, 1}, // D1 20 - {&DDRD, &PIND, &PORTD, 0}, // D0 21 - {&DDRA, &PINA, &PORTA, 0}, // A0 22 - {&DDRA, &PINA, &PORTA, 1}, // A1 23 - {&DDRA, &PINA, &PORTA, 2}, // A2 24 - {&DDRA, &PINA, &PORTA, 3}, // A3 25 - {&DDRA, &PINA, &PORTA, 4}, // A4 26 - {&DDRA, &PINA, &PORTA, 5}, // A5 27 - {&DDRA, &PINA, &PORTA, 6}, // A6 28 - {&DDRA, &PINA, &PORTA, 7}, // A7 29 - {&DDRC, &PINC, &PORTC, 7}, // C7 30 - {&DDRC, &PINC, &PORTC, 6}, // C6 31 - {&DDRC, &PINC, &PORTC, 5}, // C5 32 - {&DDRC, &PINC, &PORTC, 4}, // C4 33 - {&DDRC, &PINC, &PORTC, 3}, // C3 34 - {&DDRC, &PINC, &PORTC, 2}, // C2 35 - {&DDRC, &PINC, &PORTC, 1}, // C1 36 - {&DDRC, &PINC, &PORTC, 0}, // C0 37 - {&DDRD, &PIND, &PORTD, 7}, // D7 38 - {&DDRG, &PING, &PORTG, 2}, // G2 39 - {&DDRG, &PING, &PORTG, 1}, // G1 40 - {&DDRG, &PING, &PORTG, 0}, // G0 41 - {&DDRL, &PINL, &PORTL, 7}, // L7 42 - {&DDRL, &PINL, &PORTL, 6}, // L6 43 - {&DDRL, &PINL, &PORTL, 5}, // L5 44 - {&DDRL, &PINL, &PORTL, 4}, // L4 45 - {&DDRL, &PINL, &PORTL, 3}, // L3 46 - {&DDRL, &PINL, &PORTL, 2}, // L2 47 - {&DDRL, &PINL, &PORTL, 1}, // L1 48 - {&DDRL, &PINL, &PORTL, 0}, // L0 49 - {&DDRB, &PINB, &PORTB, 3}, // B3 50 - {&DDRB, &PINB, &PORTB, 2}, // B2 51 - {&DDRB, &PINB, &PORTB, 1}, // B1 52 - {&DDRB, &PINB, &PORTB, 0}, // B0 53 - {&DDRF, &PINF, &PORTF, 0}, // F0 54 - {&DDRF, &PINF, &PORTF, 1}, // F1 55 - {&DDRF, &PINF, &PORTF, 2}, // F2 56 - {&DDRF, &PINF, &PORTF, 3}, // F3 57 - {&DDRF, &PINF, &PORTF, 4}, // F4 58 - {&DDRF, &PINF, &PORTF, 5}, // F5 59 - {&DDRF, &PINF, &PORTF, 6}, // F6 60 - {&DDRF, &PINF, &PORTF, 7}, // F7 61 - {&DDRK, &PINK, &PORTK, 0}, // K0 62 - {&DDRK, &PINK, &PORTK, 1}, // K1 63 - {&DDRK, &PINK, &PORTK, 2}, // K2 64 - {&DDRK, &PINK, &PORTK, 3}, // K3 65 - {&DDRK, &PINK, &PORTK, 4}, // K4 66 - {&DDRK, &PINK, &PORTK, 5}, // K5 67 - {&DDRK, &PINK, &PORTK, 6}, // K6 68 - {&DDRK, &PINK, &PORTK, 7} // K7 69 + {&DDRE, &PINE, &PORTE, 0}, // E0 0 + {&DDRE, &PINE, &PORTE, 1}, // E1 1 + {&DDRE, &PINE, &PORTE, 4}, // E4 2 + {&DDRE, &PINE, &PORTE, 5}, // E5 3 + {&DDRG, &PING, &PORTG, 5}, // G5 4 + {&DDRE, &PINE, &PORTE, 3}, // E3 5 + {&DDRH, &PINH, &PORTH, 3}, // H3 6 + {&DDRH, &PINH, &PORTH, 4}, // H4 7 + {&DDRH, &PINH, &PORTH, 5}, // H5 8 + {&DDRH, &PINH, &PORTH, 6}, // H6 9 + {&DDRB, &PINB, &PORTB, 4}, // B4 10 + {&DDRB, &PINB, &PORTB, 5}, // B5 11 + {&DDRB, &PINB, &PORTB, 6}, // B6 12 + {&DDRB, &PINB, &PORTB, 7}, // B7 13 + {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 + {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 + {&DDRH, &PINH, &PORTH, 1}, // H1 16 + {&DDRH, &PINH, &PORTH, 0}, // H0 17 + {&DDRD, &PIND, &PORTD, 3}, // D3 18 + {&DDRD, &PIND, &PORTD, 2}, // D2 19 + {&DDRD, &PIND, &PORTD, 1}, // D1 20 + {&DDRD, &PIND, &PORTD, 0}, // D0 21 + {&DDRA, &PINA, &PORTA, 0}, // A0 22 + {&DDRA, &PINA, &PORTA, 1}, // A1 23 + {&DDRA, &PINA, &PORTA, 2}, // A2 24 + {&DDRA, &PINA, &PORTA, 3}, // A3 25 + {&DDRA, &PINA, &PORTA, 4}, // A4 26 + {&DDRA, &PINA, &PORTA, 5}, // A5 27 + {&DDRA, &PINA, &PORTA, 6}, // A6 28 + {&DDRA, &PINA, &PORTA, 7}, // A7 29 + {&DDRC, &PINC, &PORTC, 7}, // C7 30 + {&DDRC, &PINC, &PORTC, 6}, // C6 31 + {&DDRC, &PINC, &PORTC, 5}, // C5 32 + {&DDRC, &PINC, &PORTC, 4}, // C4 33 + {&DDRC, &PINC, &PORTC, 3}, // C3 34 + {&DDRC, &PINC, &PORTC, 2}, // C2 35 + {&DDRC, &PINC, &PORTC, 1}, // C1 36 + {&DDRC, &PINC, &PORTC, 0}, // C0 37 + {&DDRD, &PIND, &PORTD, 7}, // D7 38 + {&DDRG, &PING, &PORTG, 2}, // G2 39 + {&DDRG, &PING, &PORTG, 1}, // G1 40 + {&DDRG, &PING, &PORTG, 0}, // G0 41 + {&DDRL, &PINL, &PORTL, 7}, // L7 42 + {&DDRL, &PINL, &PORTL, 6}, // L6 43 + {&DDRL, &PINL, &PORTL, 5}, // L5 44 + {&DDRL, &PINL, &PORTL, 4}, // L4 45 + {&DDRL, &PINL, &PORTL, 3}, // L3 46 + {&DDRL, &PINL, &PORTL, 2}, // L2 47 + {&DDRL, &PINL, &PORTL, 1}, // L1 48 + {&DDRL, &PINL, &PORTL, 0}, // L0 49 + {&DDRB, &PINB, &PORTB, 3}, // B3 50 + {&DDRB, &PINB, &PORTB, 2}, // B2 51 + {&DDRB, &PINB, &PORTB, 1}, // B1 52 + {&DDRB, &PINB, &PORTB, 0}, // B0 53 + {&DDRF, &PINF, &PORTF, 0}, // F0 54 + {&DDRF, &PINF, &PORTF, 1}, // F1 55 + {&DDRF, &PINF, &PORTF, 2}, // F2 56 + {&DDRF, &PINF, &PORTF, 3}, // F3 57 + {&DDRF, &PINF, &PORTF, 4}, // F4 58 + {&DDRF, &PINF, &PORTF, 5}, // F5 59 + {&DDRF, &PINF, &PORTF, 6}, // F6 60 + {&DDRF, &PINF, &PORTF, 7}, // F7 61 + {&DDRK, &PINK, &PORTK, 0}, // K0 62 + {&DDRK, &PINK, &PORTK, 1}, // K1 63 + {&DDRK, &PINK, &PORTK, 2}, // K2 64 + {&DDRK, &PINK, &PORTK, 3}, // K3 65 + {&DDRK, &PINK, &PORTK, 4}, // K4 66 + {&DDRK, &PINK, &PORTK, 5}, // K5 67 + {&DDRK, &PINK, &PORTK, 6}, // K6 68 + {&DDRK, &PINK, &PORTK, 7} // K7 69 }; //------------------------------------------------------------------------------ -#elif (defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && defined(CORE_MICRODUINO) +#elif (defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && \ + defined(CORE_MICRODUINO) // Microduino Core+ // Two Wire (aka I2C) ports @@ -188,38 +189,38 @@ uint8_t const MISO_PIN = 12; uint8_t const SCK_PIN = 13; static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 PD0 - {&DDRD, &PIND, &PORTD, 1}, // D1 PD1 - {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 - {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 - {&DDRB, &PINB, &PORTB, 0}, // D4 PB0 - {&DDRB, &PINB, &PORTB, 1}, // D5 PB1 - {&DDRB, &PINB, &PORTB, 2}, // D6 PB2 - {&DDRB, &PINB, &PORTB, 3}, // D7 PB3 - {&DDRD, &PIND, &PORTD, 6}, // D8 PD6 - {&DDRD, &PIND, &PORTD, 5}, // D9 PD5 - {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 - {&DDRB, &PINB, &PORTB, 5}, // D11 PB5 - {&DDRB, &PINB, &PORTB, 6}, // D12 PB6 - {&DDRB, &PINB, &PORTB, 7}, // D13 PB7 - {&DDRC, &PINC, &PORTC, 7}, // D14 PC7 - {&DDRC, &PINC, &PORTC, 6}, // D15 PC6 - {&DDRC, &PINC, &PORTC, 5}, // D16 PC5 - {&DDRC, &PINC, &PORTC, 4}, // D17 PC4 - {&DDRC, &PINC, &PORTC, 3}, // D18 PC3 - {&DDRC, &PINC, &PORTC, 2}, // D19 PC2 - {&DDRC, &PINC, &PORTC, 1}, // D20 PC1 - {&DDRC, &PINC, &PORTC, 0}, // D21 PC0 - {&DDRD, &PIND, &PORTD, 4}, // D22 PD4 - {&DDRD, &PIND, &PORTD, 7}, // D23 PD7 - {&DDRA, &PINA, &PORTA, 7}, // D24 PA7 - {&DDRA, &PINA, &PORTA, 6}, // D25 PA6 - {&DDRA, &PINA, &PORTA, 5}, // D26 PA5 - {&DDRA, &PINA, &PORTA, 4}, // D27 PA4 - {&DDRA, &PINA, &PORTA, 3}, // D28 PA3 - {&DDRA, &PINA, &PORTA, 2}, // D29 PA2 - {&DDRA, &PINA, &PORTA, 1}, // D30 PA1 - {&DDRA, &PINA, &PORTA, 0} // D31 PA0 + {&DDRD, &PIND, &PORTD, 0}, // D0 PD0 + {&DDRD, &PIND, &PORTD, 1}, // D1 PD1 + {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 + {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 + {&DDRB, &PINB, &PORTB, 0}, // D4 PB0 + {&DDRB, &PINB, &PORTB, 1}, // D5 PB1 + {&DDRB, &PINB, &PORTB, 2}, // D6 PB2 + {&DDRB, &PINB, &PORTB, 3}, // D7 PB3 + {&DDRD, &PIND, &PORTD, 6}, // D8 PD6 + {&DDRD, &PIND, &PORTD, 5}, // D9 PD5 + {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 + {&DDRB, &PINB, &PORTB, 5}, // D11 PB5 + {&DDRB, &PINB, &PORTB, 6}, // D12 PB6 + {&DDRB, &PINB, &PORTB, 7}, // D13 PB7 + {&DDRC, &PINC, &PORTC, 7}, // D14 PC7 + {&DDRC, &PINC, &PORTC, 6}, // D15 PC6 + {&DDRC, &PINC, &PORTC, 5}, // D16 PC5 + {&DDRC, &PINC, &PORTC, 4}, // D17 PC4 + {&DDRC, &PINC, &PORTC, 3}, // D18 PC3 + {&DDRC, &PINC, &PORTC, 2}, // D19 PC2 + {&DDRC, &PINC, &PORTC, 1}, // D20 PC1 + {&DDRC, &PINC, &PORTC, 0}, // D21 PC0 + {&DDRD, &PIND, &PORTD, 4}, // D22 PD4 + {&DDRD, &PIND, &PORTD, 7}, // D23 PD7 + {&DDRA, &PINA, &PORTA, 7}, // D24 PA7 + {&DDRA, &PINA, &PORTA, 6}, // D25 PA6 + {&DDRA, &PINA, &PORTA, 5}, // D26 PA5 + {&DDRA, &PINA, &PORTA, 4}, // D27 PA4 + {&DDRA, &PINA, &PORTA, 3}, // D28 PA3 + {&DDRA, &PINA, &PORTA, 2}, // D29 PA2 + {&DDRA, &PINA, &PORTA, 1}, // D30 PA1 + {&DDRA, &PINA, &PORTA, 0} // D31 PA0 }; //------------------------------------------------------------------------------ #elif defined(__AVR_ATmega128RFA1__) && defined(CORE_MICRODUINO) @@ -236,28 +237,28 @@ uint8_t const MISO_PIN = 12; uint8_t const SCK_PIN = 13; static const pin_map_t digitalPinMap[] = { - {&DDRD, &PINE, &PORTE, 0}, // D0 PE0 - {&DDRD, &PINE, &PORTE, 1}, // D1 PE1 - {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 - {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 - {&DDRB, &PINE, &PORTE, 3}, // D4 PE3 - {&DDRB, &PINE, &PORTE, 4}, // D5 PE4 - {&DDRB, &PINE, &PORTE, 5}, // D6 PE5 - {&DDRB, &PINB, &PORTB, 7}, // D7 PB7 - {&DDRD, &PINB, &PORTB, 6}, // D8 PB6 - {&DDRD, &PINB, &PORTB, 5}, // D9 PB5 - {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 - {&DDRB, &PINB, &PORTB, 2}, // D11 PB2 - {&DDRB, &PINB, &PORTB, 3}, // D12 PB3 - {&DDRB, &PINB, &PORTB, 1}, // D13 PB1 - {&DDRF, &PINF, &PORTF, 7}, // D14 PF7 - {&DDRF, &PINF, &PORTF, 6}, // D15 PF6 - {&DDRF, &PINF, &PORTF, 5}, // D16 PF5 - {&DDRF, &PINF, &PORTF, 4}, // D17 PF4 - {&DDRD, &PIND, &PORTD, 1}, // D18 PD1 - {&DDRD, &PIND, &PORTD, 0}, // D19 PD0 - {&DDRF, &PINF, &PORTF, 3}, // D20 PF3 - {&DDRF, &PINF, &PORTF, 2}, // D21 PF2 + {&DDRD, &PINE, &PORTE, 0}, // D0 PE0 + {&DDRD, &PINE, &PORTE, 1}, // D1 PE1 + {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 + {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 + {&DDRB, &PINE, &PORTE, 3}, // D4 PE3 + {&DDRB, &PINE, &PORTE, 4}, // D5 PE4 + {&DDRB, &PINE, &PORTE, 5}, // D6 PE5 + {&DDRB, &PINB, &PORTB, 7}, // D7 PB7 + {&DDRD, &PINB, &PORTB, 6}, // D8 PB6 + {&DDRD, &PINB, &PORTB, 5}, // D9 PB5 + {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 + {&DDRB, &PINB, &PORTB, 2}, // D11 PB2 + {&DDRB, &PINB, &PORTB, 3}, // D12 PB3 + {&DDRB, &PINB, &PORTB, 1}, // D13 PB1 + {&DDRF, &PINF, &PORTF, 7}, // D14 PF7 + {&DDRF, &PINF, &PORTF, 6}, // D15 PF6 + {&DDRF, &PINF, &PORTF, 5}, // D16 PF5 + {&DDRF, &PINF, &PORTF, 4}, // D17 PF4 + {&DDRD, &PIND, &PORTD, 1}, // D18 PD1 + {&DDRD, &PIND, &PORTD, 0}, // D19 PD0 + {&DDRF, &PINF, &PORTF, 3}, // D20 PF3 + {&DDRF, &PINF, &PORTF, 2}, // D21 PF2 }; //------------------------------------------------------------------------------ #elif defined(__AVR_ATmega32U4__) && defined(CORE_MICRODUINO) @@ -274,28 +275,28 @@ uint8_t const MISO_PIN = 12; uint8_t const SCK_PIN = 13; static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 2}, // D0 - PD2 - {&DDRD, &PIND, &PORTD, 3}, // D1 - PD3 - {&DDRE, &PINE, &PORTE, 6}, // D2 - PE6 - {&DDRD, &PIND, &PORTD, 6}, // D3 - PD6 - {&DDRD, &PIND, &PORTD, 7}, // D4 - PD7 - {&DDRC, &PINC, &PORTC, 6}, // D5 - PC6 - {&DDRC, &PINC, &PORTC, 7}, // D6 - PC7 - {&DDRE, &PINE, &PORTE, 7}, // D7 - PE7 - {&DDRB, &PINB, &PORTB, 6}, // D8 - PB6 - {&DDRB, &PINB, &PORTB, 5}, // D9 - PB5 - {&DDRB, &PINB, &PORTB, 0}, // D10 - PB0 - {&DDRB, &PINB, &PORTB, 2}, // D11 - MOSI - PB2 - {&DDRB, &PINB, &PORTB, 3}, // D12 -MISO - PB3 - {&DDRB, &PINB, &PORTB, 1}, // D13 -SCK - PB1 - {&DDRF, &PINF, &PORTF, 7}, // D14 - A0 - PF7 - {&DDRF, &PINF, &PORTF, 6}, // D15 - A1 - PF6 - {&DDRF, &PINF, &PORTF, 5}, // D16 - A2 - PF5 - {&DDRF, &PINF, &PORTF, 4}, // D17 - A3 - PF4 - {&DDRD, &PIND, &PORTD, 1}, // D18 - PD1 - {&DDRD, &PIND, &PORTD, 0}, // D19 - PD0 - {&DDRF, &PINF, &PORTF, 1}, // D20 - A6 - PF1 - {&DDRF, &PINF, &PORTF, 0}, // D21 - A7 - PF0 + {&DDRD, &PIND, &PORTD, 2}, // D0 - PD2 + {&DDRD, &PIND, &PORTD, 3}, // D1 - PD3 + {&DDRE, &PINE, &PORTE, 6}, // D2 - PE6 + {&DDRD, &PIND, &PORTD, 6}, // D3 - PD6 + {&DDRD, &PIND, &PORTD, 7}, // D4 - PD7 + {&DDRC, &PINC, &PORTC, 6}, // D5 - PC6 + {&DDRC, &PINC, &PORTC, 7}, // D6 - PC7 + {&DDRE, &PINE, &PORTE, 7}, // D7 - PE7 + {&DDRB, &PINB, &PORTB, 6}, // D8 - PB6 + {&DDRB, &PINB, &PORTB, 5}, // D9 - PB5 + {&DDRB, &PINB, &PORTB, 0}, // D10 - PB0 + {&DDRB, &PINB, &PORTB, 2}, // D11 - MOSI - PB2 + {&DDRB, &PINB, &PORTB, 3}, // D12 -MISO - PB3 + {&DDRB, &PINB, &PORTB, 1}, // D13 -SCK - PB1 + {&DDRF, &PINF, &PORTF, 7}, // D14 - A0 - PF7 + {&DDRF, &PINF, &PORTF, 6}, // D15 - A1 - PF6 + {&DDRF, &PINF, &PORTF, 5}, // D16 - A2 - PF5 + {&DDRF, &PINF, &PORTF, 4}, // D17 - A3 - PF4 + {&DDRD, &PIND, &PORTD, 1}, // D18 - PD1 + {&DDRD, &PIND, &PORTD, 0}, // D19 - PD0 + {&DDRF, &PINF, &PORTF, 1}, // D20 - A6 - PF1 + {&DDRF, &PINF, &PORTF, 0}, // D21 - A7 - PF0 }; //------------------------------------------------------------------------------ #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) @@ -312,38 +313,38 @@ uint8_t const MISO_PIN = 6; uint8_t const SCK_PIN = 7; static const pin_map_t digitalPinMap[] = { - {&DDRB, &PINB, &PORTB, 0}, // B0 0 - {&DDRB, &PINB, &PORTB, 1}, // B1 1 - {&DDRB, &PINB, &PORTB, 2}, // B2 2 - {&DDRB, &PINB, &PORTB, 3}, // B3 3 - {&DDRB, &PINB, &PORTB, 4}, // B4 4 - {&DDRB, &PINB, &PORTB, 5}, // B5 5 - {&DDRB, &PINB, &PORTB, 6}, // B6 6 - {&DDRB, &PINB, &PORTB, 7}, // B7 7 - {&DDRD, &PIND, &PORTD, 0}, // D0 8 - {&DDRD, &PIND, &PORTD, 1}, // D1 9 - {&DDRD, &PIND, &PORTD, 2}, // D2 10 - {&DDRD, &PIND, &PORTD, 3}, // D3 11 - {&DDRD, &PIND, &PORTD, 4}, // D4 12 - {&DDRD, &PIND, &PORTD, 5}, // D5 13 - {&DDRD, &PIND, &PORTD, 6}, // D6 14 - {&DDRD, &PIND, &PORTD, 7}, // D7 15 - {&DDRC, &PINC, &PORTC, 0}, // C0 16 - {&DDRC, &PINC, &PORTC, 1}, // C1 17 - {&DDRC, &PINC, &PORTC, 2}, // C2 18 - {&DDRC, &PINC, &PORTC, 3}, // C3 19 - {&DDRC, &PINC, &PORTC, 4}, // C4 20 - {&DDRC, &PINC, &PORTC, 5}, // C5 21 - {&DDRC, &PINC, &PORTC, 6}, // C6 22 - {&DDRC, &PINC, &PORTC, 7}, // C7 23 - {&DDRA, &PINA, &PORTA, 7}, // A7 24 - {&DDRA, &PINA, &PORTA, 6}, // A6 25 - {&DDRA, &PINA, &PORTA, 5}, // A5 26 - {&DDRA, &PINA, &PORTA, 4}, // A4 27 - {&DDRA, &PINA, &PORTA, 3}, // A3 28 - {&DDRA, &PINA, &PORTA, 2}, // A2 29 - {&DDRA, &PINA, &PORTA, 1}, // A1 30 - {&DDRA, &PINA, &PORTA, 0} // A0 31 + {&DDRB, &PINB, &PORTB, 0}, // B0 0 + {&DDRB, &PINB, &PORTB, 1}, // B1 1 + {&DDRB, &PINB, &PORTB, 2}, // B2 2 + {&DDRB, &PINB, &PORTB, 3}, // B3 3 + {&DDRB, &PINB, &PORTB, 4}, // B4 4 + {&DDRB, &PINB, &PORTB, 5}, // B5 5 + {&DDRB, &PINB, &PORTB, 6}, // B6 6 + {&DDRB, &PINB, &PORTB, 7}, // B7 7 + {&DDRD, &PIND, &PORTD, 0}, // D0 8 + {&DDRD, &PIND, &PORTD, 1}, // D1 9 + {&DDRD, &PIND, &PORTD, 2}, // D2 10 + {&DDRD, &PIND, &PORTD, 3}, // D3 11 + {&DDRD, &PIND, &PORTD, 4}, // D4 12 + {&DDRD, &PIND, &PORTD, 5}, // D5 13 + {&DDRD, &PIND, &PORTD, 6}, // D6 14 + {&DDRD, &PIND, &PORTD, 7}, // D7 15 + {&DDRC, &PINC, &PORTC, 0}, // C0 16 + {&DDRC, &PINC, &PORTC, 1}, // C1 17 + {&DDRC, &PINC, &PORTC, 2}, // C2 18 + {&DDRC, &PINC, &PORTC, 3}, // C3 19 + {&DDRC, &PINC, &PORTC, 4}, // C4 20 + {&DDRC, &PINC, &PORTC, 5}, // C5 21 + {&DDRC, &PINC, &PORTC, 6}, // C6 22 + {&DDRC, &PINC, &PORTC, 7}, // C7 23 + {&DDRA, &PINA, &PORTA, 7}, // A7 24 + {&DDRA, &PINA, &PORTA, 6}, // A6 25 + {&DDRA, &PINA, &PORTA, 5}, // A5 26 + {&DDRA, &PINA, &PORTA, 4}, // A4 27 + {&DDRA, &PINA, &PORTA, 3}, // A3 28 + {&DDRA, &PINA, &PORTA, 2}, // A2 29 + {&DDRA, &PINA, &PORTA, 1}, // A1 30 + {&DDRA, &PINA, &PORTA, 0} // A0 31 }; //------------------------------------------------------------------------------ #elif defined(__AVR_ATmega32U4__) @@ -360,30 +361,30 @@ uint8_t const MISO_PIN = 14; uint8_t const SCK_PIN = 15; static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 2}, // D2 0 - {&DDRD, &PIND, &PORTD, 3}, // D3 1 - {&DDRD, &PIND, &PORTD, 1}, // D1 2 - {&DDRD, &PIND, &PORTD, 0}, // D0 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRC, &PINC, &PORTC, 6}, // C6 5 - {&DDRD, &PIND, &PORTD, 7}, // D7 6 - {&DDRE, &PINE, &PORTE, 6}, // E6 7 - {&DDRB, &PINB, &PORTB, 4}, // B4 8 - {&DDRB, &PINB, &PORTB, 5}, // B5 9 - {&DDRB, &PINB, &PORTB, 6}, // B6 10 - {&DDRB, &PINB, &PORTB, 7}, // B7 11 - {&DDRD, &PIND, &PORTD, 6}, // D6 12 - {&DDRC, &PINC, &PORTC, 7}, // C7 13 - {&DDRB, &PINB, &PORTB, 3}, // B3 14 - {&DDRB, &PINB, &PORTB, 1}, // B1 15 - {&DDRB, &PINB, &PORTB, 2}, // B2 16 - {&DDRB, &PINB, &PORTB, 0}, // B0 17 - {&DDRF, &PINF, &PORTF, 7}, // F7 18 - {&DDRF, &PINF, &PORTF, 6}, // F6 19 - {&DDRF, &PINF, &PORTF, 5}, // F5 20 - {&DDRF, &PINF, &PORTF, 4}, // F4 21 - {&DDRF, &PINF, &PORTF, 1}, // F1 22 - {&DDRF, &PINF, &PORTF, 0}, // F0 23 + {&DDRD, &PIND, &PORTD, 2}, // D2 0 + {&DDRD, &PIND, &PORTD, 3}, // D3 1 + {&DDRD, &PIND, &PORTD, 1}, // D1 2 + {&DDRD, &PIND, &PORTD, 0}, // D0 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRC, &PINC, &PORTC, 6}, // C6 5 + {&DDRD, &PIND, &PORTD, 7}, // D7 6 + {&DDRE, &PINE, &PORTE, 6}, // E6 7 + {&DDRB, &PINB, &PORTB, 4}, // B4 8 + {&DDRB, &PINB, &PORTB, 5}, // B5 9 + {&DDRB, &PINB, &PORTB, 6}, // B6 10 + {&DDRB, &PINB, &PORTB, 7}, // B7 11 + {&DDRD, &PIND, &PORTD, 6}, // D6 12 + {&DDRC, &PINC, &PORTC, 7}, // C7 13 + {&DDRB, &PINB, &PORTB, 3}, // B3 14 + {&DDRB, &PINB, &PORTB, 1}, // B1 15 + {&DDRB, &PINB, &PORTB, 2}, // B2 16 + {&DDRB, &PINB, &PORTB, 0}, // B0 17 + {&DDRF, &PINF, &PORTF, 7}, // F7 18 + {&DDRF, &PINF, &PORTF, 6}, // F6 19 + {&DDRF, &PINF, &PORTF, 5}, // F5 20 + {&DDRF, &PINF, &PORTF, 4}, // F4 21 + {&DDRF, &PINF, &PORTF, 1}, // F1 22 + {&DDRF, &PINF, &PORTF, 0}, // F0 23 }; //------------------------------------------------------------------------------ #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) @@ -400,52 +401,52 @@ uint8_t const MISO_PIN = 23; uint8_t const SCK_PIN = 21; static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRE, &PINE, &PORTE, 0}, // E0 8 - {&DDRE, &PINE, &PORTE, 1}, // E1 9 - {&DDRC, &PINC, &PORTC, 0}, // C0 10 - {&DDRC, &PINC, &PORTC, 1}, // C1 11 - {&DDRC, &PINC, &PORTC, 2}, // C2 12 - {&DDRC, &PINC, &PORTC, 3}, // C3 13 - {&DDRC, &PINC, &PORTC, 4}, // C4 14 - {&DDRC, &PINC, &PORTC, 5}, // C5 15 - {&DDRC, &PINC, &PORTC, 6}, // C6 16 - {&DDRC, &PINC, &PORTC, 7}, // C7 17 - {&DDRE, &PINE, &PORTE, 6}, // E6 18 - {&DDRE, &PINE, &PORTE, 7}, // E7 19 - {&DDRB, &PINB, &PORTB, 0}, // B0 20 - {&DDRB, &PINB, &PORTB, 1}, // B1 21 - {&DDRB, &PINB, &PORTB, 2}, // B2 22 - {&DDRB, &PINB, &PORTB, 3}, // B3 23 - {&DDRB, &PINB, &PORTB, 4}, // B4 24 - {&DDRB, &PINB, &PORTB, 5}, // B5 25 - {&DDRB, &PINB, &PORTB, 6}, // B6 26 - {&DDRB, &PINB, &PORTB, 7}, // B7 27 - {&DDRA, &PINA, &PORTA, 0}, // A0 28 - {&DDRA, &PINA, &PORTA, 1}, // A1 29 - {&DDRA, &PINA, &PORTA, 2}, // A2 30 - {&DDRA, &PINA, &PORTA, 3}, // A3 31 - {&DDRA, &PINA, &PORTA, 4}, // A4 32 - {&DDRA, &PINA, &PORTA, 5}, // A5 33 - {&DDRA, &PINA, &PORTA, 6}, // A6 34 - {&DDRA, &PINA, &PORTA, 7}, // A7 35 - {&DDRE, &PINE, &PORTE, 4}, // E4 36 - {&DDRE, &PINE, &PORTE, 5}, // E5 37 - {&DDRF, &PINF, &PORTF, 0}, // F0 38 - {&DDRF, &PINF, &PORTF, 1}, // F1 39 - {&DDRF, &PINF, &PORTF, 2}, // F2 40 - {&DDRF, &PINF, &PORTF, 3}, // F3 41 - {&DDRF, &PINF, &PORTF, 4}, // F4 42 - {&DDRF, &PINF, &PORTF, 5}, // F5 43 - {&DDRF, &PINF, &PORTF, 6}, // F6 44 - {&DDRF, &PINF, &PORTF, 7} // F7 45 + {&DDRD, &PIND, &PORTD, 0}, // D0 0 + {&DDRD, &PIND, &PORTD, 1}, // D1 1 + {&DDRD, &PIND, &PORTD, 2}, // D2 2 + {&DDRD, &PIND, &PORTD, 3}, // D3 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRD, &PIND, &PORTD, 5}, // D5 5 + {&DDRD, &PIND, &PORTD, 6}, // D6 6 + {&DDRD, &PIND, &PORTD, 7}, // D7 7 + {&DDRE, &PINE, &PORTE, 0}, // E0 8 + {&DDRE, &PINE, &PORTE, 1}, // E1 9 + {&DDRC, &PINC, &PORTC, 0}, // C0 10 + {&DDRC, &PINC, &PORTC, 1}, // C1 11 + {&DDRC, &PINC, &PORTC, 2}, // C2 12 + {&DDRC, &PINC, &PORTC, 3}, // C3 13 + {&DDRC, &PINC, &PORTC, 4}, // C4 14 + {&DDRC, &PINC, &PORTC, 5}, // C5 15 + {&DDRC, &PINC, &PORTC, 6}, // C6 16 + {&DDRC, &PINC, &PORTC, 7}, // C7 17 + {&DDRE, &PINE, &PORTE, 6}, // E6 18 + {&DDRE, &PINE, &PORTE, 7}, // E7 19 + {&DDRB, &PINB, &PORTB, 0}, // B0 20 + {&DDRB, &PINB, &PORTB, 1}, // B1 21 + {&DDRB, &PINB, &PORTB, 2}, // B2 22 + {&DDRB, &PINB, &PORTB, 3}, // B3 23 + {&DDRB, &PINB, &PORTB, 4}, // B4 24 + {&DDRB, &PINB, &PORTB, 5}, // B5 25 + {&DDRB, &PINB, &PORTB, 6}, // B6 26 + {&DDRB, &PINB, &PORTB, 7}, // B7 27 + {&DDRA, &PINA, &PORTA, 0}, // A0 28 + {&DDRA, &PINA, &PORTA, 1}, // A1 29 + {&DDRA, &PINA, &PORTA, 2}, // A2 30 + {&DDRA, &PINA, &PORTA, 3}, // A3 31 + {&DDRA, &PINA, &PORTA, 4}, // A4 32 + {&DDRA, &PINA, &PORTA, 5}, // A5 33 + {&DDRA, &PINA, &PORTA, 6}, // A6 34 + {&DDRA, &PINA, &PORTA, 7}, // A7 35 + {&DDRE, &PINE, &PORTE, 4}, // E4 36 + {&DDRE, &PINE, &PORTE, 5}, // E5 37 + {&DDRF, &PINF, &PORTF, 0}, // F0 38 + {&DDRF, &PINF, &PORTF, 1}, // F1 39 + {&DDRF, &PINF, &PORTF, 2}, // F2 40 + {&DDRF, &PINF, &PORTF, 3}, // F3 41 + {&DDRF, &PINF, &PORTF, 4}, // F4 42 + {&DDRF, &PINF, &PORTF, 5}, // F5 43 + {&DDRF, &PINF, &PORTF, 6}, // F6 44 + {&DDRF, &PINF, &PORTF, 7} // F7 45 }; //------------------------------------------------------------------------------ #else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) @@ -462,44 +463,44 @@ uint8_t const MISO_PIN = 12; uint8_t const SCK_PIN = 13; static const pin_map_t digitalPinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRB, &PINB, &PORTB, 0}, // B0 8 - {&DDRB, &PINB, &PORTB, 1}, // B1 9 - {&DDRB, &PINB, &PORTB, 2}, // B2 10 - {&DDRB, &PINB, &PORTB, 3}, // B3 11 - {&DDRB, &PINB, &PORTB, 4}, // B4 12 - {&DDRB, &PINB, &PORTB, 5}, // B5 13 - {&DDRC, &PINC, &PORTC, 0}, // C0 14 - {&DDRC, &PINC, &PORTC, 1}, // C1 15 - {&DDRC, &PINC, &PORTC, 2}, // C2 16 - {&DDRC, &PINC, &PORTC, 3}, // C3 17 - {&DDRC, &PINC, &PORTC, 4}, // C4 18 - {&DDRC, &PINC, &PORTC, 5} // C5 19 + {&DDRD, &PIND, &PORTD, 0}, // D0 0 + {&DDRD, &PIND, &PORTD, 1}, // D1 1 + {&DDRD, &PIND, &PORTD, 2}, // D2 2 + {&DDRD, &PIND, &PORTD, 3}, // D3 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRD, &PIND, &PORTD, 5}, // D5 5 + {&DDRD, &PIND, &PORTD, 6}, // D6 6 + {&DDRD, &PIND, &PORTD, 7}, // D7 7 + {&DDRB, &PINB, &PORTB, 0}, // B0 8 + {&DDRB, &PINB, &PORTB, 1}, // B1 9 + {&DDRB, &PINB, &PORTB, 2}, // B2 10 + {&DDRB, &PINB, &PORTB, 3}, // B3 11 + {&DDRB, &PINB, &PORTB, 4}, // B4 12 + {&DDRB, &PINB, &PORTB, 5}, // B5 13 + {&DDRC, &PINC, &PORTC, 0}, // C0 14 + {&DDRC, &PINC, &PORTC, 1}, // C1 15 + {&DDRC, &PINC, &PORTC, 2}, // C2 16 + {&DDRC, &PINC, &PORTC, 3}, // C3 17 + {&DDRC, &PINC, &PORTC, 4}, // C4 18 + {&DDRC, &PINC, &PORTC, 5} // C5 19 }; -#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //------------------------------------------------------------------------------ -static const uint8_t digitalPinCount = sizeof(digitalPinMap) / sizeof(pin_map_t); +static const uint8_t digitalPinCount = + sizeof(digitalPinMap) / sizeof(pin_map_t); uint8_t badPinNumber(void) -__attribute__((error("Pin number is too large or not a constant"))); + __attribute__((error("Pin number is too large or not a constant"))); -static inline __attribute__((always_inline)) -uint8_t getPinMode(uint8_t pin) { +static inline __attribute__((always_inline)) uint8_t getPinMode(uint8_t pin) { if (__builtin_constant_p(pin) && pin < digitalPinCount) { return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1; } else { return badPinNumber(); } } -static inline __attribute__((always_inline)) -void setPinMode(uint8_t pin, uint8_t mode) { +static inline __attribute__((always_inline)) void setPinMode(uint8_t pin, + uint8_t mode) { if (__builtin_constant_p(pin) && pin < digitalPinCount) { if (mode) { *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit; @@ -510,16 +511,16 @@ void setPinMode(uint8_t pin, uint8_t mode) { badPinNumber(); } } -static inline __attribute__((always_inline)) -uint8_t fastDigitalRead(uint8_t pin) { +static inline __attribute__((always_inline)) uint8_t +fastDigitalRead(uint8_t pin) { if (__builtin_constant_p(pin) && pin < digitalPinCount) { return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1; } else { return badPinNumber(); } } -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, uint8_t value) { +static inline __attribute__((always_inline)) void +fastDigitalWrite(uint8_t pin, uint8_t value) { if (__builtin_constant_p(pin) && pin < digitalPinCount) { if (value) { *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit; @@ -530,22 +531,22 @@ void fastDigitalWrite(uint8_t pin, uint8_t value) { badPinNumber(); } } -#endif // Sd2PinMap_h +#endif // Sd2PinMap_h -#elif defined (__CPU_ARC__) +#elif defined(__CPU_ARC__) -#if defined (__ARDUINO_ARC__) - // Two Wire (aka I2C) ports - uint8_t const SDA_PIN = 18; - uint8_t const SCL_PIN = 19; +#if defined(__ARDUINO_ARC__) +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 18; +uint8_t const SCL_PIN = 19; - // SPI port - uint8_t const SS_PIN = 10; - uint8_t const MOSI_PIN = 11; - uint8_t const MISO_PIN = 12; - uint8_t const SCK_PIN = 13; +// SPI port +uint8_t const SS_PIN = 10; +uint8_t const MOSI_PIN = 11; +uint8_t const MISO_PIN = 12; +uint8_t const SCK_PIN = 13; -#endif // Arduino ARC +#endif // Arduino ARC #else #error Architecture or board not supported. diff --git a/src/utility/SdFat.h b/src/utility/SdFat.h index d5c48f6..0f6ccd5 100644 --- a/src/utility/SdFat.h +++ b/src/utility/SdFat.h @@ -26,12 +26,13 @@ #include -#if defined (__AVR__) || defined (__CPU_ARC__) - #include +#if defined(__AVR__) || defined(__CPU_ARC__) +#include #endif -#include "Sd2Card.h" #include "FatStructs.h" +#include "Sd2Card.h" #include + //------------------------------------------------------------------------------ /** Allow use of deprecated functions if non-zero @@ -43,18 +44,18 @@ class SdVolume; //============================================================================== // SdFile class -#ifdef O_RDONLY //ARDUINO_ARCH_MBED - #undef O_READ - #undef O_RDONLY - #undef O_WRITE - #undef O_WRONLY - #undef O_RDWR - #undef O_ACCMODE - #undef O_APPEND - #undef O_SYNC - #undef O_CREAT - #undef O_EXCL - #undef O_TRUNC +#ifdef O_RDONLY // ARDUINO_ARCH_MBED +#undef O_READ +#undef O_RDONLY +#undef O_WRITE +#undef O_WRONLY +#undef O_RDWR +#undef O_ACCMODE +#undef O_APPEND +#undef O_SYNC +#undef O_CREAT +#undef O_EXCL +#undef O_TRUNC #endif // flags for ls() @@ -123,17 +124,13 @@ static inline uint8_t FAT_MONTH(uint16_t fatDate) { return (fatDate >> 5) & 0XF; } /** day part of FAT directory date field */ -static inline uint8_t FAT_DAY(uint16_t fatDate) { - return fatDate & 0X1F; -} +static inline uint8_t FAT_DAY(uint16_t fatDate) { return fatDate & 0X1F; } /** time field for FAT directory entry */ static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { return hour << 11 | minute << 5 | second >> 1; } /** hour part of FAT directory time field */ -static inline uint8_t FAT_HOUR(uint16_t fatTime) { - return fatTime >> 11; -} +static inline uint8_t FAT_HOUR(uint16_t fatTime) { return fatTime >> 11; } /** minute part of FAT directory time field */ static inline uint8_t FAT_MINUTE(uint16_t fatTime) { return (fatTime >> 5) & 0X3F; @@ -152,317 +149,286 @@ uint16_t const FAT_DEFAULT_TIME = (1 << 11); \brief Access FAT16 and FAT32 files on SD and SDHC cards. */ class SdFile : public Print { - public: - /** Create an instance of SdFile. */ - SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} - /** - writeError is set to true if an error occurs during a write(). - Set writeError to false before calling print() and/or write() and check - for true after calls to print() and/or write(). - */ - //bool writeError; - /** - Cancel unbuffered reads for this file. - See setUnbufferedRead() - */ - void clearUnbufferedRead(void) { - flags_ &= ~F_FILE_UNBUFFERED_READ; - } - uint8_t close(void); - uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - uint8_t createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size); - /** \return The current cluster number for a file or directory. */ - uint32_t curCluster(void) const { - return curCluster_; - } - /** \return The current position for a file or directory. */ - uint32_t curPosition(void) const { - return curPosition_; - } - /** - Set the date/time callback function - - \param[in] dateTime The user's call back function. The callback - function is of the form: - - \code - void dateTime(uint16_t* date, uint16_t* time) { - uint16_t year; - uint8_t month, day, hour, minute, second; - - // User gets date and time from GPS or real-time clock here - - // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); - - // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); - } - \endcode - - Sets the function that is called when a file is created or when - a file's directory entry is modified by sync(). All timestamps, - access, creation, and modify, are set when a file is created. - sync() maintains the last access date and last modify date/time. - - See the timestamp() function. - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)) { - dateTime_ = dateTime; - } - /** - Cancel the date/time callback function. - */ - static void dateTimeCallbackCancel(void) { - // use explicit zero since NULL is not defined for Sanguino - dateTime_ = 0; - } - /** \return Address of the block that contains this file's directory. */ - uint32_t dirBlock(void) const { - return dirBlock_; - } - uint8_t dirEntry(dir_t* dir); - /** \return Index of this file's directory in the block dirBlock. */ - uint8_t dirIndex(void) const { - return dirIndex_; - } - static void dirName(const dir_t& dir, char* name); - /** \return The total number of bytes in a file or directory. */ - uint32_t fileSize(void) const { - return fileSize_; - } - /** \return The first cluster number for a file or directory. */ - uint32_t firstCluster(void) const { - return firstCluster_; - } - /** \return True if this is a SdFile for a directory else false. */ - uint8_t isDir(void) const { - return type_ >= FAT_FILE_TYPE_MIN_DIR; - } - /** \return True if this is a SdFile for a file else false. */ - uint8_t isFile(void) const { - return type_ == FAT_FILE_TYPE_NORMAL; - } - /** \return True if this is a SdFile for an open file/directory else false. */ - uint8_t isOpen(void) const { - return type_ != FAT_FILE_TYPE_CLOSED; - } - /** \return True if this is a SdFile for a subdirectory else false. */ - uint8_t isSubDir(void) const { - return type_ == FAT_FILE_TYPE_SUBDIR; - } - /** \return True if this is a SdFile for the root directory. */ - uint8_t isRoot(void) const { - return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; - } - void ls(uint8_t flags = 0, uint8_t indent = 0); - uint8_t makeDir(SdFile* dir, const char* dirName); - uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag); - uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag); - - uint8_t openRoot(SdVolume* vol); - static void printDirName(const dir_t& dir, uint8_t width); - static void printFatDate(uint16_t fatDate); - static void printFatTime(uint16_t fatTime); - static void printTwoDigits(uint8_t v); - /** - 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. - */ - int16_t read(void) { - uint8_t b; - return read(&b, 1) == 1 ? b : -1; - } - int16_t read(void* buf, uint16_t nbyte); - int8_t readDir(dir_t* dir); - static uint8_t remove(SdFile* dirFile, const char* fileName); - uint8_t remove(void); - /** Set the file's current position to zero. */ - void rewind(void) { - curPosition_ = curCluster_ = 0; - } - uint8_t rmDir(void); - uint8_t rmRfStar(void); - /** Set the files position to current position + \a pos. See seekSet(). */ - uint8_t seekCur(uint32_t pos) { - return seekSet(curPosition_ + pos); - } - /** - Set the files current position to end of file. Useful to position - a file for append. See seekSet(). - */ - uint8_t seekEnd(void) { - return seekSet(fileSize_); - } - uint8_t seekSet(uint32_t pos); - /** - Use unbuffered reads to access this file. Used with Wave - Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. - - Not recommended for normal applications. - */ - void setUnbufferedRead(void) { - if (isFile()) { - flags_ |= F_FILE_UNBUFFERED_READ; - } - } - uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, - uint8_t hour, uint8_t minute, uint8_t second); - uint8_t sync(uint8_t blocking = 1); - /** Type of this SdFile. You should use isFile() or isDir() instead of type() - if possible. - - \return The file or directory type. - */ - uint8_t type(void) const { - return type_; - } - uint8_t truncate(uint32_t size); - /** \return Unbuffered read flag. */ - uint8_t unbufferedRead(void) const { - return flags_ & F_FILE_UNBUFFERED_READ; - } - /** \return SdVolume that contains this file. */ - SdVolume* volume(void) const { - return vol_; - } - size_t write(uint8_t b); - size_t write(const void* buf, uint16_t nbyte); - size_t write(const char* str); - #ifdef __AVR__ - void write_P(PGM_P str); - void writeln_P(PGM_P str); - #endif - int availableForWrite(void); - //------------------------------------------------------------------------------ - #if ALLOW_DEPRECATED_FUNCTIONS - // Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: - uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - */ - uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT - return contiguousRange(&bgnBlock, &endBlock); - } - /** \deprecated Use: - uint8_t SdFile::createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size) - */ - uint8_t createContiguous(SdFile& dirFile, // NOLINT - const char* fileName, uint32_t size) { - return createContiguous(&dirFile, fileName, size); - } - - /** - \deprecated Use: - static void SdFile::dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)); - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT - oldDateTime_ = dateTime; - dateTime_ = dateTime ? oldToNew : 0; - } - /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ - uint8_t dirEntry(dir_t& dir) { - return dirEntry(&dir); // NOLINT - } - /** \deprecated Use: - uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); - */ - uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT - return makeDir(&dir, dirName); - } - /** \deprecated Use: - uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, // NOLINT - const char* fileName, uint8_t oflag) { - return open(&dirFile, fileName, oflag); - } - /** \deprecated Do not use in new apps */ - uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT - return open(dirFile, fileName, O_RDWR); - } - /** \deprecated Use: - uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); - */ - uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT - return open(&dirFile, index, oflag); - } - /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ - uint8_t openRoot(SdVolume& vol) { - return openRoot(&vol); // NOLINT - } - - /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ - int8_t readDir(dir_t& dir) { - return readDir(&dir); // NOLINT - } - /** \deprecated Use: - static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); - */ - static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT - return remove(&dirFile, fileName); - } - //------------------------------------------------------------------------------ - // rest are private - private: - static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT - static void oldToNew(uint16_t* date, uint16_t* time) { - uint16_t d; - uint16_t t; - oldDateTime_(d, t); - *date = d; - *time = t; - } - #endif // ALLOW_DEPRECATED_FUNCTIONS - private: - // bits defined in flags_ - // should be 0XF - static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); - // available bits - static uint8_t const F_FILE_NON_BLOCKING_WRITE = 0X10; - // a new cluster was added to the file - static uint8_t const F_FILE_CLUSTER_ADDED = 0X20; - // use unbuffered SD read - static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; - // sync of directory entry required - static uint8_t const F_FILE_DIR_DIRTY = 0X80; - - // make sure F_OFLAG is ok - #if ((F_FILE_NON_BLOCKING_WRITE | F_FILE_CLUSTER_ADDED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG) +public: + /** Create an instance of SdFile. */ + SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} + /** + writeError is set to true if an error occurs during a write(). + Set writeError to false before calling print() and/or write() and check + for true after calls to print() and/or write(). + */ + // bool writeError; + /** + Cancel unbuffered reads for this file. + See setUnbufferedRead() + */ + void clearUnbufferedRead(void) { flags_ &= ~F_FILE_UNBUFFERED_READ; } + uint8_t close(void); + uint8_t contiguousRange(uint32_t *bgnBlock, uint32_t *endBlock); + uint8_t createContiguous(SdFile *dirFile, const char *fileName, + uint32_t size); + /** \return The current cluster number for a file or directory. */ + uint32_t curCluster(void) const { return curCluster_; } + /** \return The current position for a file or directory. */ + uint32_t curPosition(void) const { return curPosition_; } + /** + Set the date/time callback function + + \param[in] dateTime The user's call back function. The callback + function is of the form: + + \code + void dateTime(uint16_t* date, uint16_t* time) { + uint16_t year; + uint8_t month, day, hour, minute, second; + + // User gets date and time from GPS or real-time clock here + + // return date using FAT_DATE macro to format fields + * *date = FAT_DATE(year, month, day); + + // return time using FAT_TIME macro to format fields + * *time = FAT_TIME(hour, minute, second); + } + \endcode + + Sets the function that is called when a file is created or when + a file's directory entry is modified by sync(). All timestamps, + access, creation, and modify, are set when a file is created. + sync() maintains the last access date and last modify date/time. + + See the timestamp() function. + */ + static void dateTimeCallback(void (*dateTime)(uint16_t *date, + uint16_t *time)) { + dateTime_ = dateTime; + } + /** + Cancel the date/time callback function. + */ + static void dateTimeCallbackCancel(void) { + // use explicit zero since NULL is not defined for Sanguino + dateTime_ = 0; + } + /** \return Address of the block that contains this file's directory. */ + uint32_t dirBlock(void) const { return dirBlock_; } + uint8_t dirEntry(dir_t *dir); + /** \return Index of this file's directory in the block dirBlock. */ + uint8_t dirIndex(void) const { return dirIndex_; } + static void dirName(const dir_t &dir, char *name); + /** \return The total number of bytes in a file or directory. */ + uint32_t fileSize(void) const { return fileSize_; } + /** \return The first cluster number for a file or directory. */ + uint32_t firstCluster(void) const { return firstCluster_; } + /** \return True if this is a SdFile for a directory else false. */ + uint8_t isDir(void) const { return type_ >= FAT_FILE_TYPE_MIN_DIR; } + /** \return True if this is a SdFile for a file else false. */ + uint8_t isFile(void) const { return type_ == FAT_FILE_TYPE_NORMAL; } + /** \return True if this is a SdFile for an open file/directory else false. */ + uint8_t isOpen(void) const { return type_ != FAT_FILE_TYPE_CLOSED; } + /** \return True if this is a SdFile for a subdirectory else false. */ + uint8_t isSubDir(void) const { return type_ == FAT_FILE_TYPE_SUBDIR; } + /** \return True if this is a SdFile for the root directory. */ + uint8_t isRoot(void) const { + return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; + } + void ls(uint8_t flags = 0, uint8_t indent = 0); + uint8_t makeDir(SdFile *dir, const char *dirName); + uint8_t open(SdFile *dirFile, uint16_t index, uint8_t oflag); + uint8_t open(SdFile *dirFile, const char *fileName, uint8_t oflag); + + uint8_t openRoot(SdVolume *vol); + static void printDirName(const dir_t &dir, uint8_t width); + static void printFatDate(uint16_t fatDate); + static void printFatTime(uint16_t fatTime); + static void printTwoDigits(uint8_t v); + /** + 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. + */ + int16_t read(void) { + uint8_t b; + return read(&b, 1) == 1 ? b : -1; + } + int16_t read(void *buf, uint16_t nbyte); + int8_t readDir(dir_t *dir); + static uint8_t remove(SdFile *dirFile, const char *fileName); + uint8_t remove(void); + /** Set the file's current position to zero. */ + void rewind(void) { curPosition_ = curCluster_ = 0; } + uint8_t rmDir(void); + uint8_t rmRfStar(void); + /** Set the files position to current position + \a pos. See seekSet(). */ + uint8_t seekCur(uint32_t pos) { return seekSet(curPosition_ + pos); } + /** + Set the files current position to end of file. Useful to position + a file for append. See seekSet(). + */ + uint8_t seekEnd(void) { return seekSet(fileSize_); } + uint8_t seekSet(uint32_t pos); + /** + Use unbuffered reads to access this file. Used with Wave + Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. + + Not recommended for normal applications. + */ + void setUnbufferedRead(void) { + if (isFile()) { + flags_ |= F_FILE_UNBUFFERED_READ; + } + } + uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, + uint8_t hour, uint8_t minute, uint8_t second); + uint8_t sync(uint8_t blocking = 1); + /** Type of this SdFile. You should use isFile() or isDir() instead of type() + if possible. + + \return The file or directory type. + */ + uint8_t type(void) const { return type_; } + uint8_t truncate(uint32_t size); + /** \return Unbuffered read flag. */ + uint8_t unbufferedRead(void) const { return flags_ & F_FILE_UNBUFFERED_READ; } + /** \return SdVolume that contains this file. */ + SdVolume *volume(void) const { return vol_; } + size_t write(uint8_t b); + size_t write(const void *buf, uint16_t nbyte); + size_t write(const char *str); +#ifdef __AVR__ + void write_P(PGM_P str); + void writeln_P(PGM_P str); +#endif + int availableForWrite(void); +//------------------------------------------------------------------------------ +#if ALLOW_DEPRECATED_FUNCTIONS + // Deprecated functions - suppress cpplint warnings with NOLINT comment + /** \deprecated Use: + uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); + */ + uint8_t contiguousRange(uint32_t &bgnBlock, uint32_t &endBlock) { // NOLINT + return contiguousRange(&bgnBlock, &endBlock); + } + /** \deprecated Use: + uint8_t SdFile::createContiguous(SdFile* dirFile, + const char* fileName, uint32_t size) + */ + uint8_t createContiguous(SdFile &dirFile, // NOLINT + const char *fileName, uint32_t size) { + return createContiguous(&dirFile, fileName, size); + } + + /** + \deprecated Use: + static void SdFile::dateTimeCallback( + void (*dateTime)(uint16_t* date, uint16_t* time)); + */ + static void dateTimeCallback(void (*dateTime)(uint16_t &date, + uint16_t &time)) { // NOLINT + oldDateTime_ = dateTime; + dateTime_ = dateTime ? oldToNew : 0; + } + /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ + uint8_t dirEntry(dir_t &dir) { + return dirEntry(&dir); // NOLINT + } + /** \deprecated Use: + uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); + */ + uint8_t makeDir(SdFile &dir, const char *dirName) { // NOLINT + return makeDir(&dir, dirName); + } + /** \deprecated Use: + uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); + */ + uint8_t open(SdFile &dirFile, // NOLINT + const char *fileName, uint8_t oflag) { + return open(&dirFile, fileName, oflag); + } + /** \deprecated Do not use in new apps */ + uint8_t open(SdFile &dirFile, const char *fileName) { // NOLINT + return open(dirFile, fileName, O_RDWR); + } + /** \deprecated Use: + uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); + */ + uint8_t open(SdFile &dirFile, uint16_t index, uint8_t oflag) { // NOLINT + return open(&dirFile, index, oflag); + } + /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ + uint8_t openRoot(SdVolume &vol) { + return openRoot(&vol); // NOLINT + } + + /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ + int8_t readDir(dir_t &dir) { + return readDir(&dir); // NOLINT + } + /** \deprecated Use: + static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); + */ + static uint8_t remove(SdFile &dirFile, const char *fileName) { // NOLINT + return remove(&dirFile, fileName); + } + //------------------------------------------------------------------------------ + // rest are private +private: + static void (*oldDateTime_)(uint16_t &date, uint16_t &time); // NOLINT + static void oldToNew(uint16_t *date, uint16_t *time) { + uint16_t d; + uint16_t t; + oldDateTime_(d, t); + *date = d; + *time = t; + } +#endif // ALLOW_DEPRECATED_FUNCTIONS +private: + // bits defined in flags_ + // should be 0XF + static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); + // available bits + static uint8_t const F_FILE_NON_BLOCKING_WRITE = 0X10; + // a new cluster was added to the file + static uint8_t const F_FILE_CLUSTER_ADDED = 0X20; + // use unbuffered SD read + static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; + // sync of directory entry required + static uint8_t const F_FILE_DIR_DIRTY = 0X80; + +// make sure F_OFLAG is ok +#if ((F_FILE_NON_BLOCKING_WRITE | F_FILE_CLUSTER_ADDED | \ + F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & \ + F_OFLAG) #error flags_ bits conflict - #endif // flags_ bits - - // private data - uint8_t flags_; // See above for definition of flags_ bits - uint8_t type_; // type of file see above for values - uint32_t curCluster_; // cluster for current file position - uint32_t curPosition_; // current file position in bytes from beginning - uint32_t dirBlock_; // SD block that contains directory entry for file - uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF - uint32_t fileSize_; // file size in bytes - uint32_t firstCluster_; // first cluster of file - SdVolume* vol_; // volume where file is located - - // private functions - uint8_t addCluster(void); - uint8_t addDirCluster(void); - dir_t* cacheDirEntry(uint8_t action); - static void (*dateTime_)(uint16_t* date, uint16_t* time); - static uint8_t make83Name(const char* str, uint8_t* name); - uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); - dir_t* readDirCache(void); +#endif // flags_ bits + + // private data + uint8_t flags_; // See above for definition of flags_ bits + uint8_t type_; // type of file see above for values + uint32_t curCluster_; // cluster for current file position + uint32_t curPosition_; // current file position in bytes from beginning + uint32_t dirBlock_; // SD block that contains directory entry for file + uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF + uint32_t fileSize_; // file size in bytes + uint32_t firstCluster_; // first cluster of file + SdVolume *vol_; // volume where file is located + + // private functions + uint8_t addCluster(void); + uint8_t addDirCluster(void); + dir_t *cacheDirEntry(uint8_t action); + static void (*dateTime_)(uint16_t *date, uint16_t *time); + static uint8_t make83Name(const char *str, uint8_t *name); + uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); + dir_t *readDirCache(void); #ifdef MOCK_PINS_COUNT - int writeError; - public: - int getWriteError() { return writeError; } - void setWriteError(int value = 1) { writeError = value; } - void clearWriteError() { writeError = 0; } + int writeError; + +public: + int getWriteError() { return writeError; } + void setWriteError(int value = 1) { writeError = value; } + void clearWriteError() { writeError = 0; } #endif }; //============================================================================== @@ -472,17 +438,17 @@ class SdFile : public Print { */ union cache_t { /** Used to access cached file data blocks. */ - uint8_t data[512]; + uint8_t data[512]; /** Used to access cached FAT16 entries. */ uint16_t fat16[256]; /** Used to access cached FAT32 entries. */ uint32_t fat32[128]; /** Used to access cached directory entries. */ - dir_t dir[16]; + dir_t dir[16]; /** Used to access a cached MasterBoot Record. */ - mbr_t mbr; + mbr_t mbr; /** Used to access to a cached FAT boot sector. */ - fbs_t fbs; + fbs_t fbs; }; //------------------------------------------------------------------------------ /** @@ -490,162 +456,130 @@ union cache_t { \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. */ class SdVolume { - public: - /** Create an instance of SdVolume */ - SdVolume(void) : allocSearchStart_(2), fatType_(0) {} - /** Clear the cache and returns a pointer to the cache. Used by the WaveRP - recorder to do raw write to the SD card. Not for normal apps. - */ - static uint8_t* cacheClear(void) { - cacheFlush(); - cacheBlockNumber_ = 0XFFFFFFFF; - return cacheBuffer_.data; - } - /** - Initialize a FAT volume. Try partition one first then try super - floppy format. - - \param[in] dev The Sd2Card where the volume is located. - - \return The value one, true, is returned for success and - the value zero, false, is returned for failure. Reasons for - failure include not finding a valid partition, not finding a valid - FAT file system or an I/O error. - */ - uint8_t init(Sd2Card* dev) { - return init(dev, 1) ? true : init(dev, 0); - } - uint8_t init(Sd2Card* dev, uint8_t part); - - // inline functions that return volume info - /** \return The volume's cluster size in blocks. */ - uint8_t blocksPerCluster(void) const { - return blocksPerCluster_; - } - /** \return The number of blocks in one FAT. */ - uint32_t blocksPerFat(void) const { - return blocksPerFat_; - } - /** \return The total number of clusters in the volume. */ - uint32_t clusterCount(void) const { - return clusterCount_; - } - /** \return The shift count required to multiply by blocksPerCluster. */ - uint8_t clusterSizeShift(void) const { - return clusterSizeShift_; - } - /** \return The logical block number for the start of file data. */ - uint32_t dataStartBlock(void) const { - return dataStartBlock_; - } - /** \return The number of FAT structures on the volume. */ - uint8_t fatCount(void) const { - return fatCount_; - } - /** \return The logical block number for the start of the first FAT. */ - uint32_t fatStartBlock(void) const { - return fatStartBlock_; - } - /** \return The FAT type of the volume. Values are 12, 16 or 32. */ - uint8_t fatType(void) const { - return fatType_; - } - /** \return The number of entries in the root directory for FAT16 volumes. */ - uint32_t rootDirEntryCount(void) const { - return rootDirEntryCount_; - } - /** \return The logical block number for the start of the root directory - on FAT16 volumes or the first cluster number on FAT32 volumes. */ - uint32_t rootDirStart(void) const { - return rootDirStart_; - } - /** return a pointer to the Sd2Card object for this volume */ - static Sd2Card* sdCard(void) { - return sdCard_; - } - //------------------------------------------------------------------------------ - #if ALLOW_DEPRECATED_FUNCTIONS - // Deprecated functions - suppress cpplint warnings with NOLINT comment - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ - uint8_t init(Sd2Card& dev) { - return init(&dev); // NOLINT - } - - /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ - uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT - return init(&dev, part); - } - #endif // ALLOW_DEPRECATED_FUNCTIONS - //------------------------------------------------------------------------------ - private: - // Allow SdFile access to SdVolume private data. - friend class SdFile; - - // value for action argument in cacheRawBlock to indicate read from cache - static uint8_t const CACHE_FOR_READ = 0; - // value for action argument in cacheRawBlock to indicate cache dirty - static uint8_t const CACHE_FOR_WRITE = 1; - - static cache_t cacheBuffer_; // 512 byte cache for device blocks - static uint32_t cacheBlockNumber_; // Logical number of block in the cache - static Sd2Card* sdCard_; // Sd2Card object for cache - static uint8_t cacheDirty_; // cacheFlush() will write block if true - static uint32_t cacheMirrorBlock_; // block number for mirror FAT - // - uint32_t allocSearchStart_; // start cluster for alloc search - uint8_t blocksPerCluster_; // cluster size in blocks - uint32_t blocksPerFat_; // FAT size in blocks - uint32_t clusterCount_; // clusters in one FAT - uint8_t clusterSizeShift_; // shift to convert cluster count to block count - uint32_t dataStartBlock_; // first data block number - uint8_t fatCount_; // number of FATs on volume - uint32_t fatStartBlock_; // start block for first FAT - uint8_t fatType_; // volume type (12, 16, OR 32) - uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir - uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 - //---------------------------------------------------------------------------- - uint8_t allocContiguous(uint32_t count, uint32_t* curCluster); - uint8_t blockOfCluster(uint32_t position) const { - return (position >> 9) & (blocksPerCluster_ - 1); - } - uint32_t clusterStartBlock(uint32_t cluster) const { - return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_); - } - uint32_t blockNumber(uint32_t cluster, uint32_t position) const { - return clusterStartBlock(cluster) + blockOfCluster(position); - } - static uint8_t cacheFlush(uint8_t blocking = 1); - static uint8_t cacheMirrorBlockFlush(uint8_t blocking); - static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); - static void cacheSetDirty(void) { - cacheDirty_ |= CACHE_FOR_WRITE; - } - static uint8_t cacheZeroBlock(uint32_t blockNumber); - uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const; - uint8_t fatGet(uint32_t cluster, uint32_t* value) const; - uint8_t fatPut(uint32_t cluster, uint32_t value); - uint8_t fatPutEOC(uint32_t cluster) { - return fatPut(cluster, 0x0FFFFFFF); - } - uint8_t freeChain(uint32_t cluster); - uint8_t isEOC(uint32_t cluster) const { - return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); - } - uint8_t readBlock(uint32_t block, uint8_t* dst) { - return sdCard_->readBlock(block, dst); - } - uint8_t readData(uint32_t block, uint16_t offset, - uint16_t count, uint8_t* dst) { - return sdCard_->readData(block, offset, count, dst); - } - uint8_t writeBlock(uint32_t block, const uint8_t* dst, uint8_t blocking = 1) { - return sdCard_->writeBlock(block, dst, blocking); - } - uint8_t isBusy(void) { - return sdCard_->isBusy(); - } - uint8_t isCacheMirrorBlockDirty(void) { - return (cacheMirrorBlock_ != 0); - } +public: + /** Create an instance of SdVolume */ + SdVolume(void) : allocSearchStart_(2), fatType_(0) {} + /** Clear the cache and returns a pointer to the cache. Used by the WaveRP + recorder to do raw write to the SD card. Not for normal apps. + */ + static uint8_t *cacheClear(void) { + cacheFlush(); + cacheBlockNumber_ = 0XFFFFFFFF; + return cacheBuffer_.data; + } + /** + Initialize a FAT volume. Try partition one first then try super + floppy format. + + \param[in] dev The Sd2Card where the volume is located. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. Reasons for + failure include not finding a valid partition, not finding a valid + FAT file system or an I/O error. + */ + uint8_t init(Sd2Card *dev) { return init(dev, 1) ? true : init(dev, 0); } + uint8_t init(Sd2Card *dev, uint8_t part); + + // inline functions that return volume info + /** \return The volume's cluster size in blocks. */ + uint8_t blocksPerCluster(void) const { return blocksPerCluster_; } + /** \return The number of blocks in one FAT. */ + uint32_t blocksPerFat(void) const { return blocksPerFat_; } + /** \return The total number of clusters in the volume. */ + uint32_t clusterCount(void) const { return clusterCount_; } + /** \return The shift count required to multiply by blocksPerCluster. */ + uint8_t clusterSizeShift(void) const { return clusterSizeShift_; } + /** \return The logical block number for the start of file data. */ + uint32_t dataStartBlock(void) const { return dataStartBlock_; } + /** \return The number of FAT structures on the volume. */ + uint8_t fatCount(void) const { return fatCount_; } + /** \return The logical block number for the start of the first FAT. */ + uint32_t fatStartBlock(void) const { return fatStartBlock_; } + /** \return The FAT type of the volume. Values are 12, 16 or 32. */ + uint8_t fatType(void) const { return fatType_; } + /** \return The number of entries in the root directory for FAT16 volumes. */ + uint32_t rootDirEntryCount(void) const { return rootDirEntryCount_; } + /** \return The logical block number for the start of the root directory + on FAT16 volumes or the first cluster number on FAT32 volumes. */ + uint32_t rootDirStart(void) const { return rootDirStart_; } + /** return a pointer to the Sd2Card object for this volume */ + static Sd2Card *sdCard(void) { return sdCard_; } +//------------------------------------------------------------------------------ +#if ALLOW_DEPRECATED_FUNCTIONS + // Deprecated functions - suppress cpplint warnings with NOLINT comment + /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ + uint8_t init(Sd2Card &dev) { + return init(&dev); // NOLINT + } + + /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ + uint8_t init(Sd2Card &dev, uint8_t part) { // NOLINT + return init(&dev, part); + } +#endif // ALLOW_DEPRECATED_FUNCTIONS + //------------------------------------------------------------------------------ +private: + // Allow SdFile access to SdVolume private data. + friend class SdFile; + + // value for action argument in cacheRawBlock to indicate read from cache + static uint8_t const CACHE_FOR_READ = 0; + // value for action argument in cacheRawBlock to indicate cache dirty + static uint8_t const CACHE_FOR_WRITE = 1; + + static cache_t cacheBuffer_; // 512 byte cache for device blocks + static uint32_t cacheBlockNumber_; // Logical number of block in the cache + static Sd2Card *sdCard_; // Sd2Card object for cache + static uint8_t cacheDirty_; // cacheFlush() will write block if true + static uint32_t cacheMirrorBlock_; // block number for mirror FAT + // + uint32_t allocSearchStart_; // start cluster for alloc search + uint8_t blocksPerCluster_; // cluster size in blocks + uint32_t blocksPerFat_; // FAT size in blocks + uint32_t clusterCount_; // clusters in one FAT + uint8_t clusterSizeShift_; // shift to convert cluster count to block count + uint32_t dataStartBlock_; // first data block number + uint8_t fatCount_; // number of FATs on volume + uint32_t fatStartBlock_; // start block for first FAT + uint8_t fatType_; // volume type (12, 16, OR 32) + uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir + uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 + //---------------------------------------------------------------------------- + uint8_t allocContiguous(uint32_t count, uint32_t *curCluster); + uint8_t blockOfCluster(uint32_t position) const { + return (position >> 9) & (blocksPerCluster_ - 1); + } + uint32_t clusterStartBlock(uint32_t cluster) const { + return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_); + } + uint32_t blockNumber(uint32_t cluster, uint32_t position) const { + return clusterStartBlock(cluster) + blockOfCluster(position); + } + static uint8_t cacheFlush(uint8_t blocking = 1); + static uint8_t cacheMirrorBlockFlush(uint8_t blocking); + static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); + static void cacheSetDirty(void) { cacheDirty_ |= CACHE_FOR_WRITE; } + static uint8_t cacheZeroBlock(uint32_t blockNumber); + uint8_t chainSize(uint32_t beginCluster, uint32_t *size) const; + uint8_t fatGet(uint32_t cluster, uint32_t *value) const; + uint8_t fatPut(uint32_t cluster, uint32_t value); + uint8_t fatPutEOC(uint32_t cluster) { return fatPut(cluster, 0x0FFFFFFF); } + uint8_t freeChain(uint32_t cluster); + uint8_t isEOC(uint32_t cluster) const { + return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); + } + uint8_t readBlock(uint32_t block, uint8_t *dst) { + return sdCard_->readBlock(block, dst); + } + uint8_t readData(uint32_t block, uint16_t offset, uint16_t count, + uint8_t *dst) { + return sdCard_->readData(block, offset, count, dst); + } + uint8_t writeBlock(uint32_t block, const uint8_t *dst, uint8_t blocking = 1) { + return sdCard_->writeBlock(block, dst, blocking); + } + uint8_t isBusy(void) { return sdCard_->isBusy(); } + uint8_t isCacheMirrorBlockDirty(void) { return (cacheMirrorBlock_ != 0); } }; -#endif // SdFat_h +#endif // SdFat_h diff --git a/src/utility/SdFatUtil.h b/src/utility/SdFatUtil.h index 00227ec..0422e5c 100644 --- a/src/utility/SdFatUtil.h +++ b/src/utility/SdFatUtil.h @@ -25,14 +25,14 @@ */ #include #ifdef __AVR__ - #include - /** Store and print a string in flash memory.*/ - #define PgmPrint(x) SerialPrint_P(PSTR(x)) - /** Store and print a string in flash memory followed by a CR/LF.*/ - #define PgmPrintln(x) SerialPrintln_P(PSTR(x)) - /** Defined so doxygen works for function definitions. */ +#include +/** Store and print a string in flash memory.*/ +#define PgmPrint(x) SerialPrint_P(PSTR(x)) +/** Store and print a string in flash memory followed by a CR/LF.*/ +#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) +/** Defined so doxygen works for function definitions. */ #endif -#define NOINLINE __attribute__((noinline,unused)) +#define NOINLINE __attribute__((noinline, unused)) #define UNUSEDOK __attribute__((unused)) #if UINTPTR_MAX == 0xFFFF @@ -48,17 +48,17 @@ typedef int64_t ptr_as_int; //------------------------------------------------------------------------------ /** Return the number of bytes currently free in RAM. */ static UNUSEDOK int FreeRam(void) { - extern int __bss_end; - extern int* __brkval; + extern int __bss_end; + extern int *__brkval; int free_memory; if (reinterpret_cast(__brkval) == 0) { // if no heap use from end of bss section - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(&__bss_end); + free_memory = reinterpret_cast(&free_memory) - + reinterpret_cast(&__bss_end); } else { // use from top of stack to heap - free_memory = reinterpret_cast(&free_memory) - - reinterpret_cast(__brkval); + free_memory = reinterpret_cast(&free_memory) - + reinterpret_cast(__brkval); } return free_memory; } @@ -84,5 +84,5 @@ static NOINLINE void SerialPrintln_P(PGM_P str) { SerialPrint_P(str); Serial.println(); } -#endif // __AVR__ -#endif // #define SdFatUtil_h +#endif // __AVR__ +#endif // #define SdFatUtil_h diff --git a/src/utility/SdFatmainpage.h b/src/utility/SdFatmainpage.h index 1e6d96f..d72119b 100644 --- a/src/utility/SdFatmainpage.h +++ b/src/utility/SdFatmainpage.h @@ -45,11 +45,11 @@ A number of example are provided in the SdFat/examples folder. These were developed to test SdFat and illustrate its use. - SdFat was developed for high speed data recording. SdFat was used to implement - an audio record/play class, WaveRP, for the Adafruit Wave Shield. This - application uses special Sd2Card calls to write to contiguous files in raw mode. - These functions reduce write latency so that audio can be recorded with the - small amount of RAM in the Arduino. + SdFat was developed for high speed data recording. SdFat was used to + implement an audio record/play class, WaveRP, for the Adafruit Wave Shield. + This application uses special Sd2Card calls to write to contiguous files in + raw mode. These functions reduce write latency so that audio can be recorded + with the small amount of RAM in the Arduino. \section SDcard SD\SDHC Cards @@ -79,9 +79,9 @@ controllers when resistor voltage dividers are used. The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the - 74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield - uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the - 74LCX245. + 74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave + Shield uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based + on the 74LCX245. If you are using a resistor based level shifter and are having problems try setting the SPI bus frequency to 4 MHz. This can be done by using @@ -89,7 +89,8 @@ \section comment Bugs and Comments - If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net. + If you wish to report bugs or have comments, send email to + fat16lib@sbcglobal.net. \section SdFatClass SdFat Usage @@ -109,16 +110,16 @@ \note The Arduino Print class uses character - at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink - function to control when data is written to the SD card. + at a time writes so it was necessary to use a \link SdFile::sync() sync() + \endlink function to control when data is written to the SD card. \par - An application which writes to a file using \link Print::print() print()\endlink, - \link Print::println() println() \endlink - or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink + An application which writes to a file using \link Print::print() + print()\endlink, \link Print::println() println() \endlink or \link + SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink at the appropriate time to force data and directory information to be written - to the SD Card. Data and directory information are also written to the SD card - when \link SdFile::close() close() \endlink is called. + to the SD Card. Data and directory information are also written to the SD + card when \link SdFile::close() close() \endlink is called. \par Applications must use care calling \link SdFile::sync() sync() \endlink @@ -127,8 +128,9 @@ the block that contains the directory entry for update, writing the directory block back and reading back the current data block. - It is possible to open a file with two or more instances of SdFile. A file may - be corrupted if data is written to the file by more than one instance of SdFile. + It is possible to open a file with two or more instances of SdFile. A file + may be corrupted if data is written to the file by more than one instance of + SdFile. \section HowTo How to format SD Cards as FAT Volumes diff --git a/src/utility/SdFile.cpp b/src/utility/SdFile.cpp index 18a1db6..16e01ec 100644 --- a/src/utility/SdFile.cpp +++ b/src/utility/SdFile.cpp @@ -19,17 +19,17 @@ */ #include "SdFat.h" #ifdef __AVR__ - #include +#include #endif #include //------------------------------------------------------------------------------ // callback function for date/time -void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL; +void (*SdFile::dateTime_)(uint16_t *date, uint16_t *time) = NULL; #if ALLOW_DEPRECATED_FUNCTIONS - // suppress cpplint warnings with NOLINT comment - void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL; // NOLINT -#endif // ALLOW_DEPRECATED_FUNCTIONS +// suppress cpplint warnings with NOLINT comment +void (*SdFile::oldDateTime_)(uint16_t &date, uint16_t &time) = NULL; // NOLINT +#endif // ALLOW_DEPRECATED_FUNCTIONS //------------------------------------------------------------------------------ // add a cluster to a file uint8_t SdFile::addCluster() { @@ -67,7 +67,7 @@ uint8_t SdFile::addDirCluster(void) { //------------------------------------------------------------------------------ // cache a file's directory entry // return pointer to cached entry or null for failure -dir_t* SdFile::cacheDirEntry(uint8_t action) { +dir_t *SdFile::cacheDirEntry(uint8_t action) { if (!SdVolume::cacheRawBlock(dirBlock_, action)) { return NULL; } @@ -101,13 +101,13 @@ uint8_t SdFile::close(void) { Reasons for failure include file is not contiguous, file has zero length or an I/O error occurred. */ -uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { +uint8_t SdFile::contiguousRange(uint32_t *bgnBlock, uint32_t *endBlock) { // error if no blocks if (firstCluster_ == 0) { return false; } - for (uint32_t c = firstCluster_; ; c++) { + for (uint32_t c = firstCluster_;; c++) { uint32_t next; if (!vol_->fatGet(c, &next)) { return false; @@ -120,8 +120,7 @@ uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { return false; } *bgnBlock = vol_->clusterStartBlock(firstCluster_); - *endBlock = vol_->clusterStartBlock(c) - + vol_->blocksPerCluster_ - 1; + *endBlock = vol_->clusterStartBlock(c) + vol_->blocksPerCluster_ - 1; return true; } } @@ -145,8 +144,8 @@ uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { directory is full or an I/O error. */ -uint8_t SdFile::createContiguous(SdFile* dirFile, - const char* fileName, uint32_t size) { +uint8_t SdFile::createContiguous(SdFile *dirFile, const char *fileName, + uint32_t size) { // don't allow zero length file if (size == 0) { return false; @@ -178,14 +177,14 @@ uint8_t SdFile::createContiguous(SdFile* dirFile, \return The value one, true, is returned for success and the value zero, false, is returned for failure. */ -uint8_t SdFile::dirEntry(dir_t* dir) { +uint8_t SdFile::dirEntry(dir_t *dir) { // make sure fields on SD are correct if (!sync()) { return false; } // read entry - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); + dir_t *p = cacheDirEntry(SdVolume::CACHE_FOR_READ); if (!p) { return false; } @@ -202,7 +201,7 @@ uint8_t SdFile::dirEntry(dir_t* dir) { \param[in] dir The directory structure containing the name. \param[out] name A 13 byte char array for the formatted name. */ -void SdFile::dirName(const dir_t& dir, char* name) { +void SdFile::dirName(const dir_t &dir, char *name) { uint8_t j = 0; for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ') { @@ -230,7 +229,7 @@ void SdFile::dirName(const dir_t& dir, char* name) { list to indicate subdirectory level. */ void SdFile::ls(uint8_t flags, uint8_t indent) { - dir_t* p; + dir_t *p; rewind(); while ((p = readDirCache())) { @@ -283,9 +282,9 @@ void SdFile::ls(uint8_t flags, uint8_t indent) { } //------------------------------------------------------------------------------ // format directory name field from a 8.3 name string -uint8_t SdFile::make83Name(const char* str, uint8_t* name) { +uint8_t SdFile::make83Name(const char *str, uint8_t *name) { uint8_t c; - uint8_t n = 7; // max index for part before dot + uint8_t n = 7; // max index for part before dot uint8_t i = 0; // blank fill name and extension while (i < 11) { @@ -295,31 +294,33 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) { while ((c = *str++) != '\0') { if (c == '.') { if (n == 10) { - return false; // only one dot allowed + return false; // only one dot allowed } - n = 10; // max index for full 8.3 name - i = 8; // place for extension + n = 10; // max index for full 8.3 name + i = 8; // place for extension } else { // illegal FAT characters uint8_t b; - #if defined(__AVR__) +#if defined(__AVR__) PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); - while ((b = pgm_read_byte(p++))) if (b == c) { + while ((b = pgm_read_byte(p++))) + if (b == c) { return false; } - #elif defined(__arm__) +#elif defined(__arm__) const uint8_t valid[] = "|<>^+=?/[];,*\"\\"; const uint8_t *p = valid; - while ((b = *p++)) if (b == c) { + while ((b = *p++)) + if (b == c) { return false; } - #endif +#endif // check size and only allow ASCII printable characters if (i > n || c < 0X21 || c > 0X7E) { return false; } // only upper case allowed in 8.3 names - convert lower to upper - name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); + name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); } } // must have a file name, extension is optional @@ -338,7 +339,7 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) { Reasons for failure include this SdFile is already open, \a dir is not a directory, \a dirName is invalid or already exists in \a dir. */ -uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { +uint8_t SdFile::makeDir(SdFile *dir, const char *dirName) { dir_t d; // create a normal file @@ -361,7 +362,7 @@ uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { } // cache entry - should already be in cache due to sync() call - dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + dir_t *p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); if (!p) { return false; } @@ -450,9 +451,9 @@ uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { a directory, \a fileName is invalid, the file does not exist or can't be opened in the access mode specified by oflag. */ -uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { +uint8_t SdFile::open(SdFile *dirFile, const char *fileName, uint8_t oflag) { uint8_t dname[11]; - dir_t* p; + dir_t *p; // error if already open if (isOpen()) { @@ -562,7 +563,7 @@ uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { See open() by fileName for definition of flags and return values. */ -uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { +uint8_t SdFile::open(SdFile *dirFile, uint16_t index, uint8_t oflag) { // error if already open if (isOpen()) { return false; @@ -581,14 +582,14 @@ uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { } // read entry into cache - dir_t* p = dirFile->readDirCache(); + dir_t *p = dirFile->readDirCache(); if (p == NULL) { return false; } // error if empty slot or '.' or '..' - if (p->name[0] == DIR_NAME_FREE || - p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED || + p->name[0] == '.') { return false; } // open cached entry @@ -598,7 +599,7 @@ uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { // open a cached directory entry. Assumes vol_ is initializes uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { // location of entry in cache - dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex; + dir_t *p = SdVolume::cacheBuffer_.dir + dirIndex; // write or truncate is an error for a directory or read-only file if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { @@ -650,7 +651,7 @@ uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { Reasons for failure include the FAT volume has not been initialized or it a FAT12 volume. */ -uint8_t SdFile::openRoot(SdVolume* vol) { +uint8_t SdFile::openRoot(SdVolume *vol) { // error if file is already open if (isOpen()) { return false; @@ -689,7 +690,7 @@ uint8_t SdFile::openRoot(SdVolume* vol) { \param[in] dir The directory structure containing the name. \param[in] width Blank fill name if length is less than \a width. */ -void SdFile::printDirName(const dir_t& dir, uint8_t width) { +void SdFile::printDirName(const dir_t &dir, uint8_t width) { uint8_t w = 0; for (uint8_t i = 0; i < 11; i++) { if (dir.name[i] == ' ') { @@ -766,8 +767,8 @@ void SdFile::printTwoDigits(uint8_t v) { read() called before a file has been opened, corrupt file system or an I/O error occurred. */ -int16_t SdFile::read(void* buf, uint16_t nbyte) { - uint8_t* dst = reinterpret_cast(buf); +int16_t SdFile::read(void *buf, uint16_t nbyte) { + uint8_t *dst = reinterpret_cast(buf); // error if not open or write only if (!isOpen() || !(flags_ & O_READ)) { @@ -782,8 +783,8 @@ int16_t SdFile::read(void* buf, uint16_t nbyte) { // amount left to read uint16_t toRead = nbyte; while (toRead > 0) { - uint32_t block; // raw device block number - uint16_t offset = curPosition_ & 0X1FF; // offset in block + uint32_t block; // raw device block number + uint16_t offset = curPosition_ & 0X1FF; // offset in block if (type_ == FAT_FILE_TYPE_ROOT16) { block = vol_->rootDirStart() + (curPosition_ >> 9); } else { @@ -821,8 +822,8 @@ int16_t SdFile::read(void* buf, uint16_t nbyte) { if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) { return -1; } - uint8_t* src = SdVolume::cacheBuffer_.data + offset; - uint8_t* end = src + n; + uint8_t *src = SdVolume::cacheBuffer_.data + offset; + uint8_t *end = src + n; while (src != end) { *dst++ = *src++; } @@ -844,7 +845,7 @@ int16_t SdFile::read(void* buf, uint16_t nbyte) { readDir() called before a directory has been opened, this is not a directory file or an I/O error occurred. */ -int8_t SdFile::readDir(dir_t* dir) { +int8_t SdFile::readDir(dir_t *dir) { int8_t n; // if not a directory file or miss-positioned return an error if (!isDir() || (0X1F & curPosition_)) { @@ -871,7 +872,7 @@ int8_t SdFile::readDir(dir_t* dir) { //------------------------------------------------------------------------------ // Read next directory entry into the cache // Assumes file is correctly positioned -dir_t* SdFile::readDirCache(void) { +dir_t *SdFile::readDirCache(void) { // error if not directory if (!isDir()) { return NULL; @@ -913,7 +914,7 @@ uint8_t SdFile::remove(void) { } // cache directory entry - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + dir_t *d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); if (!d) { return false; } @@ -946,7 +947,7 @@ uint8_t SdFile::remove(void) { \a dirFile is not a directory, \a fileName is not found or an I/O error occurred. */ -uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) { +uint8_t SdFile::remove(SdFile *dirFile, const char *fileName) { SdFile file; if (!file.open(dirFile, fileName, O_WRITE)) { return false; @@ -979,7 +980,7 @@ uint8_t SdFile::rmDir(void) { // make sure directory is empty while (curPosition_ < fileSize_) { - dir_t* p = readDirCache(); + dir_t *p = readDirCache(); if (p == NULL) { return false; } @@ -1025,7 +1026,7 @@ uint8_t SdFile::rmRfStar(void) { // remember position uint16_t index = curPosition_ / 32; - dir_t* p = readDirCache(); + dir_t *p = readDirCache(); if (!p) { return false; } @@ -1136,7 +1137,7 @@ uint8_t SdFile::sync(uint8_t blocking) { } if (flags_ & F_FILE_DIR_DIRTY) { - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + dir_t *d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); if (!d) { return false; } @@ -1201,20 +1202,13 @@ uint8_t SdFile::sync(uint8_t blocking) { the value zero, false, is returned for failure. */ uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { - if (!isOpen() - || year < 1980 - || year > 2107 - || month < 1 - || month > 12 - || day < 1 - || day > 31 - || hour > 23 - || minute > 59 - || second > 59) { + uint8_t day, uint8_t hour, uint8_t minute, + uint8_t second) { + if (!isOpen() || year < 1980 || year > 2107 || month < 1 || month > 12 || + day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) { return false; } - dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + dir_t *d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); if (!d) { return false; } @@ -1327,9 +1321,9 @@ uint8_t SdFile::truncate(uint32_t length) { for a read-only file, device is full, a corrupt file system or an I/O error. */ -size_t SdFile::write(const void* buf, uint16_t nbyte) { +size_t SdFile::write(const void *buf, uint16_t nbyte) { // convert void* to uint8_t* - must be before goto statements - const uint8_t* src = reinterpret_cast(buf); + const uint8_t *src = reinterpret_cast(buf); // number of bytes left to write - must be before goto statements uint16_t nToWrite = nbyte; @@ -1411,8 +1405,8 @@ size_t SdFile::write(const void* buf, uint16_t nbyte) { goto writeErrorReturn; } } - uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset; - uint8_t* end = dst + n; + uint8_t *dst = SdVolume::cacheBuffer_.data + blockOffset; + uint8_t *end = dst + n; while (dst != end) { *dst++ = *src++; } @@ -1438,7 +1432,7 @@ size_t SdFile::write(const void* buf, uint16_t nbyte) { writeErrorReturn: // return for write error - //writeError = true; + // writeError = true; setWriteError(); return 0; } @@ -1448,18 +1442,14 @@ size_t SdFile::write(const void* buf, uint16_t nbyte) { Use SdFile::writeError to check for errors. */ -size_t SdFile::write(uint8_t b) { - return write(&b, 1); -} +size_t SdFile::write(uint8_t b) { return write(&b, 1); } //------------------------------------------------------------------------------ /** Write a string to a file. Used by the Arduino Print class. Use SdFile::writeError to check for errors. */ -size_t SdFile::write(const char* str) { - return write(str, strlen(str)); -} +size_t SdFile::write(const char *str) { return write(str, strlen(str)); } #ifdef __AVR__ //------------------------------------------------------------------------------ /** diff --git a/src/utility/SdInfo.h b/src/utility/SdInfo.h index 6a0e087..71addd5 100644 --- a/src/utility/SdInfo.h +++ b/src/utility/SdInfo.h @@ -85,18 +85,18 @@ uint8_t const DATA_RES_ACCEPTED = 0X05; //------------------------------------------------------------------------------ typedef struct CID { // byte 0 - uint8_t mid; // Manufacturer ID + uint8_t mid; // Manufacturer ID // byte 1-2 - char oid[2]; // OEM/Application ID + char oid[2]; // OEM/Application ID // byte 3-7 - char pnm[5]; // Product name + char pnm[5]; // Product name // byte 8 - unsigned prv_m : 4; // Product revision n.m + unsigned prv_m : 4; // Product revision n.m unsigned prv_n : 4; // byte 9-12 - uint32_t psn; // Product serial number + uint32_t psn; // Product serial number // byte 13 - unsigned mdt_year_high : 4; // Manufacturing date + unsigned mdt_year_high : 4; // Manufacturing date unsigned reserved : 4; // byte 14 unsigned mdt_month : 4; @@ -156,7 +156,7 @@ typedef struct CSDV1 { unsigned write_partial : 1; unsigned write_bl_len_low : 2; // byte 14 - unsigned reserved5: 2; + unsigned reserved5 : 2; unsigned file_format : 2; unsigned tmp_write_protect : 1; unsigned perm_write_protect : 1; @@ -213,7 +213,7 @@ typedef struct CSDV2 { unsigned write_partial : 1; unsigned write_bl_len_low : 2; // byte 14 - unsigned reserved7: 2; + unsigned reserved7 : 2; unsigned file_format : 2; unsigned tmp_write_protect : 1; unsigned perm_write_protect : 1; @@ -229,4 +229,4 @@ union csd_t { csd1_t v1; csd2_t v2; }; -#endif // SdInfo_h +#endif // SdInfo_h diff --git a/src/utility/SdVolume.cpp b/src/utility/SdVolume.cpp index 60375c4..bc219fe 100644 --- a/src/utility/SdVolume.cpp +++ b/src/utility/SdVolume.cpp @@ -22,13 +22,13 @@ // raw block cache // init cacheBlockNumber_to invalid SD block number uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; -cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card -Sd2Card* SdVolume::sdCard_; // pointer to SD card object -uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true -uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT +cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card +Sd2Card *SdVolume::sdCard_; // pointer to SD card object +uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true +uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT //------------------------------------------------------------------------------ // find a contiguous group of clusters -uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { +uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t *curCluster) { // start of group uint32_t bgnCluster; @@ -167,7 +167,7 @@ uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) { } //------------------------------------------------------------------------------ // return the size in bytes of a cluster chain -uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { +uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t *size) const { uint32_t s = 0; do { if (!fatGet(cluster, &cluster)) { @@ -180,7 +180,7 @@ uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { } //------------------------------------------------------------------------------ // Fetch a FAT entry -uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { +uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t *value) const { if (cluster > (clusterCount_ + 1)) { return false; } @@ -272,7 +272,7 @@ uint8_t SdVolume::freeChain(uint32_t cluster) { failure include not finding a valid partition, not finding a valid FAT file system in the specified partition or an I/O error. */ -uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { +uint8_t SdVolume::init(Sd2Card *dev, uint8_t part) { uint32_t volumeStartBlock = 0; sdCard_ = dev; // if part == 0 assume super floppy with FAT boot sector in block zero @@ -284,10 +284,8 @@ uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) { return false; } - part_t* p = &cacheBuffer_.mbr.part[part - 1]; - if ((p->boot & 0X7F) != 0 || - p->totalSectors < 100 || - p->firstSector == 0) { + part_t *p = &cacheBuffer_.mbr.part[part - 1]; + if ((p->boot & 0X7F) != 0 || p->totalSectors < 100 || p->firstSector == 0) { // not a valid partition return false; } @@ -296,11 +294,9 @@ uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) { return false; } - bpb_t* bpb = &cacheBuffer_.fbs.bpb; - if (bpb->bytesPerSector != 512 || - bpb->fatCount == 0 || - bpb->reservedSectorCount == 0 || - bpb->sectorsPerCluster == 0) { + bpb_t *bpb = &cacheBuffer_.fbs.bpb; + if (bpb->bytesPerSector != 512 || bpb->fatCount == 0 || + bpb->reservedSectorCount == 0 || bpb->sectorsPerCluster == 0) { // not valid FAT volume return false; } @@ -315,8 +311,8 @@ uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { return false; } } - blocksPerFat_ = bpb->sectorsPerFat16 ? - bpb->sectorsPerFat16 : bpb->sectorsPerFat32; + blocksPerFat_ = + bpb->sectorsPerFat16 ? bpb->sectorsPerFat16 : bpb->sectorsPerFat32; fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount; @@ -330,8 +326,8 @@ uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511) / 512); // total blocks for FAT16 or FAT32 - uint32_t totalBlocks = bpb->totalSectors16 ? - bpb->totalSectors16 : bpb->totalSectors32; + uint32_t totalBlocks = + bpb->totalSectors16 ? bpb->totalSectors16 : bpb->totalSectors32; // total data blocks clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); From 7ed2017bfb516e1f0c988f4e10ba622ab25fa724 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 20:49:43 -0800 Subject: [PATCH 4/8] Format examples. --- examples/CardInfo/CardInfo.ino | 58 ++++++++++--------- examples/Datalogger/Datalogger.ino | 16 +++-- examples/DumpFile/DumpFile.ino | 17 +++--- examples/Files/Files.ino | 8 ++- .../NonBlockingWrite/NonBlockingWrite.ino | 15 +++-- examples/ReadWrite/ReadWrite.ino | 12 ++-- examples/listfiles/listfiles.ino | 22 ++++--- 7 files changed, 86 insertions(+), 62 deletions(-) diff --git a/examples/CardInfo/CardInfo.ino b/examples/CardInfo/CardInfo.ino index 3418e92..0b9af28 100644 --- a/examples/CardInfo/CardInfo.ino +++ b/examples/CardInfo/CardInfo.ino @@ -3,15 +3,14 @@ This example shows how use the utility libraries on which the' SD library is based in order to get info about your SD card. - Very useful for testing a card when you're not sure whether its working or not. - Pin numbers reflect the default SPI pins for Uno and Nano models - The circuit: - SD card attached to SPI bus as follows: + Very useful for testing a card when you're not sure whether its working or + not. Pin numbers reflect the default SPI pins for Uno and Nano models The + circuit: SD card attached to SPI bus as follows: ** SDO - pin 11 on Arduino Uno/Duemilanove/Diecimila ** SDI - pin 12 on Arduino Uno/Duemilanove/Diecimila ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples + Pin 10 used here for consistency with other Arduino examples created 28 Mar 2011 by Limor Fried @@ -19,8 +18,8 @@ by Tom Igoe */ // include the SD library: -#include #include +#include // set up variables using the SD utility library functions: Sd2Card card; @@ -42,7 +41,6 @@ void setup() { ; // wait for serial port to connect. Needed for native USB port only } - Serial.print("\nInitializing SD card..."); // we'll use the initialization code from the utility libraries @@ -51,8 +49,10 @@ void setup() { Serial.println("initialization failed. Things to check:"); Serial.println("* is a card inserted?"); Serial.println("* is your wiring correct?"); - Serial.println("* did you change the chipSelect pin to match your shield or module?"); - while (1); + Serial.println( + "* did you change the chipSelect pin to match your shield or module?"); + while (1) + ; } else { Serial.println("Wiring is correct and a card is present."); } @@ -61,23 +61,26 @@ void setup() { Serial.println(); Serial.print("Card type: "); switch (card.type()) { - case SD_CARD_TYPE_SD1: - Serial.println("SD1"); - break; - case SD_CARD_TYPE_SD2: - Serial.println("SD2"); - break; - case SD_CARD_TYPE_SDHC: - Serial.println("SDHC"); - break; - default: - Serial.println("Unknown"); + case SD_CARD_TYPE_SD1: + Serial.println("SD1"); + break; + case SD_CARD_TYPE_SD2: + Serial.println("SD2"); + break; + case SD_CARD_TYPE_SDHC: + Serial.println("SDHC"); + break; + default: + Serial.println("Unknown"); } - // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 + // Now we will try to open the 'volume'/'partition' - it should be FAT16 or + // FAT32 if (!volume.init(card)) { - Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"); - while (1); + Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've " + "formatted the card"); + while (1) + ; } Serial.print("Clusters: "); @@ -94,9 +97,9 @@ void setup() { Serial.print("Volume type is: FAT"); Serial.println(volume.fatType(), DEC); - volumesize = volume.blocksPerCluster(); // clusters are collections of blocks - volumesize *= volume.clusterCount(); // we'll have a lot of clusters - volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1KB) + volumesize = volume.blocksPerCluster(); // clusters are collections of blocks + volumesize *= volume.clusterCount(); // we'll have a lot of clusters + volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1KB) Serial.print("Volume size (Kb): "); Serial.println(volumesize); Serial.print("Volume size (Mb): "); @@ -113,5 +116,4 @@ void setup() { root.close(); } -void loop(void) { -} +void loop(void) {} diff --git a/examples/Datalogger/Datalogger.ino b/examples/Datalogger/Datalogger.ino index fdbacfd..0eae279 100644 --- a/examples/Datalogger/Datalogger.ino +++ b/examples/Datalogger/Datalogger.ino @@ -12,7 +12,7 @@ ** SDI - pin 12 ** CLK - pin 13 ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples + Pin 10 used here for consistency with other Arduino examples (for MKRZero SD: SDCARD_SS_PIN) created 24 Nov 2010 @@ -23,8 +23,8 @@ */ -#include #include +#include const int chipSelect = 10; @@ -32,7 +32,8 @@ void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); + while (!Serial) + ; Serial.print("Initializing SD card..."); @@ -40,9 +41,12 @@ void setup() { Serial.println("initialization failed. Things to check:"); Serial.println("1. is a card inserted?"); Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); - while (true); + Serial.println( + "3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after " + "fixing your issue!"); + while (true) + ; } Serial.println("initialization done."); diff --git a/examples/DumpFile/DumpFile.ino b/examples/DumpFile/DumpFile.ino index bb114b6..15e1213 100644 --- a/examples/DumpFile/DumpFile.ino +++ b/examples/DumpFile/DumpFile.ino @@ -11,7 +11,7 @@ ** SDI - pin 12 ** CLK - pin 13 ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples + Pin 10 used here for consistency with other Arduino examples (for MKRZero SD: SDCARD_SS_PIN) created 22 December 2010 @@ -29,7 +29,8 @@ void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); + while (!Serial) + ; Serial.print("Initializing SD card..."); @@ -37,9 +38,12 @@ void setup() { Serial.println("initialization failed. Things to check:"); Serial.println("1. is a card inserted?"); Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); - while (true); + Serial.println( + "3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after " + "fixing your issue!"); + while (true) + ; } Serial.println("initialization done."); @@ -61,5 +65,4 @@ void setup() { } } -void loop() { -} +void loop() {} diff --git a/examples/Files/Files.ino b/examples/Files/Files.ino index f19a9db..650dcbc 100644 --- a/examples/Files/Files.ino +++ b/examples/Files/Files.ino @@ -9,7 +9,7 @@ ** SDI - pin 12 ** CLK - pin 13 ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples + Pin 10 used here for consistency with other Arduino examples (for MKRZero SD: SDCARD_SS_PIN) created Nov 2010 @@ -28,13 +28,15 @@ void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); // wait for Serial Monitor to connect. Needed for native USB port boards only: -while (!Serial); + while (!Serial) + ; Serial.print("Initializing SD card..."); if (!SD.begin(chipSelect)) { Serial.println("initialization failed!"); - while (1); + while (1) + ; } Serial.println("initialization done."); diff --git a/examples/NonBlockingWrite/NonBlockingWrite.ino b/examples/NonBlockingWrite/NonBlockingWrite.ino index 082a5fb..87dbe2c 100644 --- a/examples/NonBlockingWrite/NonBlockingWrite.ino +++ b/examples/NonBlockingWrite/NonBlockingWrite.ino @@ -55,7 +55,8 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); + while (!Serial) + ; Serial.print("Initializing SD card..."); @@ -63,9 +64,12 @@ void setup() { Serial.println("initialization failed. Things to check:"); Serial.println("1. is a card inserted?"); Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); - while (true); + Serial.println( + "3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after " + "fixing your issue!"); + while (true) + ; } Serial.println("initialization done."); @@ -79,7 +83,8 @@ void setup() { if (!myFile) { Serial.print("error opening "); Serial.println(filename); - while (true); + while (true) + ; } // add some new lines to start diff --git a/examples/ReadWrite/ReadWrite.ino b/examples/ReadWrite/ReadWrite.ino index c15ecdb..5ebc03f 100644 --- a/examples/ReadWrite/ReadWrite.ino +++ b/examples/ReadWrite/ReadWrite.ino @@ -27,7 +27,8 @@ void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); + while (!Serial) + ; Serial.print("Initializing SD card..."); @@ -35,9 +36,12 @@ void setup() { Serial.println("initialization failed. Things to check:"); Serial.println("1. is a card inserted?"); Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); - while (true); + Serial.println( + "3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after " + "fixing your issue!"); + while (true) + ; } Serial.println("initialization done."); diff --git a/examples/listfiles/listfiles.ino b/examples/listfiles/listfiles.ino index 66eebb6..f532828 100644 --- a/examples/listfiles/listfiles.ino +++ b/examples/listfiles/listfiles.ino @@ -11,7 +11,7 @@ ** SDI - pin 12 ** CLK - pin 13 ** CS - depends on your SD card shield or module. - Pin 10 used here for consistency with other Arduino examples + Pin 10 used here for consistency with other Arduino examples (for MKRZero SD: SDCARD_SS_PIN) created Nov 2010 @@ -22,7 +22,7 @@ by Scott Fitzgerald modified 24 July 2020 by Tom Igoe - + This example code is in the public domain. */ @@ -32,10 +32,11 @@ const int chipSelect = 10; File root; void setup() { - // Open serial communications and wait for port to open: + // Open serial communications and wait for port to open: Serial.begin(9600); // wait for Serial Monitor to connect. Needed for native USB port boards only: - while (!Serial); + while (!Serial) + ; Serial.print("Initializing SD card..."); @@ -43,9 +44,12 @@ void setup() { Serial.println("initialization failed. Things to check:"); Serial.println("1. is a card inserted?"); Serial.println("2. is your wiring correct?"); - Serial.println("3. did you change the chipSelect pin to match your shield or module?"); - Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); - while (true); + Serial.println( + "3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after " + "fixing your issue!"); + while (true) + ; } Serial.println("initialization done."); @@ -64,8 +68,8 @@ void loop() { void printDirectory(File dir, int numTabs) { while (true) { - File entry = dir.openNextFile(); - if (! entry) { + File entry = dir.openNextFile(); + if (!entry) { // no more files break; } From 93a52f96a5274edb8907edc766c8ddff74fb8e06 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 20:51:33 -0800 Subject: [PATCH 5/8] Add include for `assert()`. --- src/SD_CI.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SD_CI.h b/src/SD_CI.h index 4ed7031..6027ecd 100644 --- a/src/SD_CI.h +++ b/src/SD_CI.h @@ -2,6 +2,7 @@ #include #ifdef MOCK_PINS_COUNT #include "SD.h" +#include #include #include #include From 932997323eff749748af83ed52e185a74e8e1df4 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 21:01:35 -0800 Subject: [PATCH 6/8] Use proper delete to avoid AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete). --- src/SD_CI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SD_CI.cpp b/src/SD_CI.cpp index 77636e2..2079540 100644 --- a/src/SD_CI.cpp +++ b/src/SD_CI.cpp @@ -28,7 +28,7 @@ bool SDClass_CI::mkdir(const char *filepath) { ptr = strchr(ptr + 1, '/'); } directories.insert(filepath); - delete path; + delete[] path; return true; } From d7f693acb8db975dbdb86b133c41897cd791f051 Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 21:14:16 -0800 Subject: [PATCH 7/8] Do proper garbage collection when removing all files. --- src/SD_CI.cpp | 8 ++++++++ src/SD_CI.h | 5 +---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/SD_CI.cpp b/src/SD_CI.cpp index 2079540..325288e 100644 --- a/src/SD_CI.cpp +++ b/src/SD_CI.cpp @@ -41,6 +41,14 @@ bool SDClass_CI::remove(const char *filepath) { return false; } +void SDClass_CI::removeAll() { + for (const auto& [key, value] : files) { + delete value; + } + directories.clear(); + files.clear(); +} + bool SDClass_CI::rmdir(const char *filepath) { if (directories.count(filepath)) { directories.erase(filepath); diff --git a/src/SD_CI.h b/src/SD_CI.h index 6027ecd..9962ba8 100644 --- a/src/SD_CI.h +++ b/src/SD_CI.h @@ -80,10 +80,7 @@ class SDClass_CI : public SDClass_Base { bool remove(const char *filepath); bool remove(const String &filepath) { return remove(filepath.c_str()); } - void removeAll() { - directories.clear(); - files.clear(); - } + void removeAll(); bool rmdir(const char *filepath); bool rmdir(const String &filepath) { return rmdir(filepath.c_str()); } From e6f4ec1c0bccc2be9ac5afa16c1218947a02c58c Mon Sep 17 00:00:00 2001 From: James Foster Date: Tue, 2 Mar 2021 21:15:21 -0800 Subject: [PATCH 8/8] Update format. --- src/SD_CI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SD_CI.cpp b/src/SD_CI.cpp index 325288e..ff677db 100644 --- a/src/SD_CI.cpp +++ b/src/SD_CI.cpp @@ -42,7 +42,7 @@ bool SDClass_CI::remove(const char *filepath) { } void SDClass_CI::removeAll() { - for (const auto& [key, value] : files) { + for (const auto &[key, value] : files) { delete value; } directories.clear();