arduino-emulator
Loading...
Searching...
No Matches
SD.h
1/*
2 SD.h
3 Copyright (c) 2025 Phil Schatzmann. All right reserved.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19#pragma once
20
21#include <sys/stat.h>
22#include <sys/types.h>
23#include <unistd.h>
24
25#include <cstdint>
26#include <filesystem>
27#include <fstream>
28#include <iostream>
29#include <string>
30
31#include "Stream.h"
32#ifdef USE_FILESYSTEM
33#include <filesystem>
34#endif
35
36#define SD_SCK_MHZ(maxMhz) (1000000UL * (maxMhz))
37#define SPI_FULL_SPEED SD_SCK_MHZ(50)
38#define SPI_DIV3_SPEED SD_SCK_MHZ(16)
39#define SPI_HALF_SPEED SD_SCK_MHZ(4)
40#define SPI_DIV6_SPEED SD_SCK_MHZ(8)
41#define SPI_QUARTER_SPEED SD_SCK_MHZ(2)
42#define SPI_EIGHTH_SPEED SD_SCK_MHZ(1)
43#define SPI_SIXTEENTH_SPEED SD_SCK_HZ(500000)
44
45#define O_RDONLY ios::in
46#define O_WRONLY ios::out
47#define O_RDWR ios::in | ios::out
48#define O_AT_END ios::ate
49#define O_APPEND ios::ate
50#define O_CREAT ios::trunc
51#define O_TRUNC ios::trunc
52#define O_EXCL 0
53#define O_SYNC 0
54#define O_READ O_RDONLY
55#define O_WRITE O_WRONLY
56#define FILE_READ ios::in
57#define FILE_WRITE ios::out
58
59#ifndef SS
60#define SS -1
61#endif
62
63using namespace std;
64
71 SdSpiConfig(int a = 0, int b = 0, int c = 0) {}
72};
73
78class File : public Stream {
79 public:
80 bool isOpen() {
81 if (filename == "") return false;
82 if (is_dir) return true;
83 bool result = file.is_open();
84 return result;
85 }
86
87 bool open(const char *name, int flags) {
88 this->filename = name;
89 int rc = stat(name, &info);
90 if ((flags == O_RDONLY) && rc == -1) {
91 // if we want to read but the file does not exist we fail
92 return false;
93 } else if (rc == 0 && info.st_mode & S_IFDIR) {
94 // file exists and it is a directory
95 is_dir = true;
96 size_bytes = 0;
97#ifdef USE_FILESYSTEM
98 // prevent authorization exceptions
99 try {
100 dir_path = std::filesystem::path(filename);
101 iterator = std::filesystem::directory_iterator({dir_path});
102 } catch (...) {
103 }
104#endif
105 return true;
106 } else {
107 is_dir = false;
108 size_bytes = rc != -1 ? info.st_size : 0;
109 file.open(filename.c_str(), toMode(flags));
110 return isOpen();
111 }
112 }
113
114 bool close() {
115 file.close();
116 return !isOpen();
117 }
118
119 size_t read(uint8_t *buffer, size_t length) {
120 return readBytes((char *)buffer, length);
121 }
122
123 size_t readBytes(char *buffer, size_t length) {
124 file.read(buffer, length);
125 return static_cast<size_t>(file.gcount());
126 }
127
128 size_t write(const uint8_t *buffer, size_t size) override {
129 file.write((const char *)buffer, size);
130 return file.good() ? size : 0;
131 }
132 size_t write(uint8_t ch) override {
133 file.put(ch);
134 return file.good() ? 1 : 0;
135 }
136 int available() override { return size_bytes - file.tellg(); };
137 int availableForWrite() override { return 1024; }
138 int read() override { return file.get(); }
139 int peek() override { return file.peek(); }
140 void flush() override {}
141 void getName(char *str, size_t len) { strncpy(str, filename.c_str(), len); }
142 bool isDir() { return is_dir; }
143 bool isHidden() { return false; }
144 bool rewind() {
145 pos = 0;
146 return is_dir;
147 }
148 bool openNext(File &dir, int flags = O_RDONLY) {
149 if (!*this) return false;
150
151 // if (pos == 0) {
152 // dir_path = std::filesystem::path(filename);
153 // iterator = std::filesystem::directory_iterator({dir_path});
154 // }
155 // pos++;
156#ifdef USE_FILESYSTEM
157 if (iterator != end(iterator)) {
158 std::filesystem::directory_entry entry = *iterator++;
159 return dir.open(entry.path().c_str(), flags);
160 }
161#endif
162 return false;
163 }
164 int dirIndex() { return pos; }
165
166 File openNextFile() {
167 File next_file;
168 openNext(next_file, O_RDONLY);
169 return next_file;
170 }
171
172 size_t size() {
173 int rc = stat(filename.c_str(), &info);
174 size_bytes = rc != -1 ? info.st_size : 0;
175 return size_bytes;
176 }
177
178 size_t position() { return file.tellg(); }
179
180 bool seek(size_t pos) {
181 file.seekg(pos);
182 return file ? true : false;
183 }
184
185 operator bool() { return isOpen(); }
186
187 bool isDirectory() { return is_dir; }
188
189 const char *name() { return filename.c_str(); }
190
191 void rewindDirectory() {
192 if (!is_dir) return;
193#ifdef USE_FILESYSTEM
194 try {
195 iterator = std::filesystem::directory_iterator(dir_path);
196 } catch (...) {
197 // Handle errors silently
198 }
199#endif
200 }
201
202 protected:
203 std::fstream file;
204 size_t size_bytes = 0;
205 bool is_dir = false;
206 int pos = 0;
207 std::string filename = "";
208 struct stat info;
209
210#ifdef USE_FILESYSTEM
211 std::filesystem::directory_iterator iterator;
212 std::filesystem::path dir_path;
213#endif
214
215 std::ios_base::openmode toMode(int flags) {
216 return (std::ios_base::openmode)flags;
217 }
218};
219
224class SdFat {
225 public:
226 bool begin(int cs = SS, int speed = 0) { return true; }
227
228 bool begin(SdSpiConfig &cfg) { return true; }
229
230 void end() {}
231
232 void errorHalt(const char *msg) {
233 puts(msg);
234 exit(0);
235 }
236 void initErrorHalt() { exit(0); }
237
238 bool exists(const char *name) {
239 struct stat info;
240 return stat(name, &info) == 0;
241 }
242
243 File open(const char *name, int flags = O_READ) {
244 File file;
245 file.open(name, flags);
246 return file;
247 }
248
249 bool remove(const char *name) { return std::remove(name) == 0; }
250 bool mkdir(const char *name) { return ::mkdir(name, 0777) == 0; }
251 bool rmdir(const char *path) {
252 int rc = ::rmdir(path);
253 return rc == 0;
254 }
255 uint64_t totalBytes() {
256 std::error_code ec;
257 const std::filesystem::space_info si = std::filesystem::space("/home", ec);
258 return si.capacity;
259 }
260 uint64_t usedBytes() {
261 std::error_code ec;
262 const std::filesystem::space_info si = std::filesystem::space("/home", ec);
263 return si.capacity - si.available;
264 }
265};
266
267static SdFat SD;
268using SDClass = SdFat;
C++ std based emulatoion ofr File.
Definition SD.h:78
C++ std based emulatoion ofr SdFat.
Definition SD.h:224
C++ std based emulatoion of SdSpiConfig.
Definition SD.h:70