/* night_ghost@ykoctpa.ru 2017 a port of SparkFun's SD class to FatFs (c) Chan because it much better and faster than sdfatlib also it was rewritten to: * distinguish between flie at directory by stat(), not by try to open * provide last error code and its text description * added tracking of opened files for global sync() * some new functions added original SparkFun readme below ---------------------------------------------- SD - a slightly more friendly wrapper for sdfatlib This library aims to expose a subset of SD card functionality in the form of a higher level "wrapper" object. License: GNU General Public License V3 (Because sdfatlib is licensed with this.) (C) Copyright 2010 SparkFun Electronics */ #ifndef __SD_H__ #define __SD_H__ #include #include #include #if defined(BOARD_SDCARD_CS_PIN) || defined(BOARD_DATAFLASH_FATFS) #include "Sd2Card.h" #include "SdFatFs.h" // replace FatFs defines to standard ones /* #define FA_READ 0x01 #define FA_OPEN_EXISTING 0x00 #if !_FS_READONLY #define FA_WRITE 0x02 #define FA_CREATE_NEW 0x04 #define FA_CREATE_ALWAYS 0x08 #define FA_OPEN_ALWAYS 0x10 */ #define O_RDONLY FA_READ #define O_WRITE FA_WRITE #define O_RDWR FA_WRITE #define O_CREAT FA_CREATE_NEW // создать новый, если существует то ошибка #define O_TRUNC FA_CREATE_ALWAYS // переписать старый #define O_APPEND 0x20 #define O_CLOEXEC 0x40 #undef EEXIST #undef EACCES #undef EISDIR #undef ENOENT #define EEXIST FR_EXIST #define EACCES FR_DENIED #define EISDIR FR_IS_DIR #define ENOENT FR_NO_FILE // flags for ls() /** ls() flag to print modify date */ uint8_t const LS_DATE = 1; /** ls() flag to print file size */ uint8_t const LS_SIZE = 2; /** ls() flag for recursive list of subdirectories */ uint8_t const LS_R = 4; typedef void (*cb_putc)(char c); class File { friend class SDClass; public: File(void); File(const char* name); size_t write(uint8_t); size_t write(const uint8_t *buf, size_t size); size_t write(const char *buf, size_t size); int read(); UINT gets(char* buf, size_t len); int peek(); int available(); void flush(); int read(void* buf, size_t len); uint8_t seek(uint32_t pos); uint32_t position(); uint32_t size(); void close(); inline operator bool() const { return (_name == NULL)? FALSE : TRUE; } // is open? char* name(void); char* fullname(void) {return _name;}; uint8_t isDirectory(); File openNextFile(uint8_t mode = FILE_READ); void rewindDirectory(void); size_t print(const char* data); size_t println(); size_t println(const char* data); // Print to Serial line void ls(cb_putc cb, uint8_t flags, uint8_t indent = 0); static void printFatDate(uint16_t fatDate, cb_putc cb); static void printFatTime(uint16_t fatTime, cb_putc cb); static void printTwoDigits(uint8_t v, cb_putc cb); static void printNumber(int16_t n, cb_putc cb); static void printStr(const char *s, cb_putc cb); void inline sync() { if(!is_dir) f_sync(&_d.fil); }; inline uint32_t firstCluster(){ return is_dir ? _d.dir.obj.sclust : _d.fil.obj.sclust; } static void syncAll(); static void addOpenFile(FIL *f); static void removeOpenFile(FIL *f); protected: // should be private? char *_name = NULL; //file or dir name #if 0 FIL _fil; // each struct contains sector buffer so this casue twice of memory use DIR _dir; #else union { FIL fil; // each struct contains sector buffer so this casue twice of memory use DIR dir; } _d; bool is_dir; #endif // static list of all open files static FIL* openFiles[16]; static uint8_t num_openFiles; }; class SDClass { public: /* Initialize the SD peripheral */ static uint8_t begin(AP_HAL::OwnPtr spi); static File open(const char *filepath, uint8_t mode); static File open(const char *filepath); static uint8_t exists(const char *filepath); static uint8_t mkdir(const char *filepath); static uint8_t remove(const char *filepath); static uint8_t rmdir(const char *filepath); static uint32_t getfree(const char *filepath, uint32_t * fssize); static uint8_t stat(const char *filepath, FILINFO* fno); static uint8_t format(const char *filepath); File openRoot(void); void inline sync() { File::syncAll(); }; friend class File; static inline Sd2Card *getCard() { return &_card; } static inline SdFatFs *getVolume() { return &_fatFs; } static FRESULT lastError; static const char * strError(FRESULT err){ return SdFatFs::strError(err); } private: static Sd2Card _card; static SdFatFs _fatFs; }; extern SDClass SD; #endif #endif