Skip to content

Commit fef4e2b

Browse files
Merge pull request #72 from CU-Robotics/SD-wrapper
SDManager wrapper class
2 parents 5defca5 + c799c6f commit fef4e2b

File tree

6 files changed

+342
-238
lines changed

6 files changed

+342
-238
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ LIBRARY_LIB = libs
3131
PROJECT_DIR = .
3232
PROJECT_SRC_DIR = src
3333
PROJECT_SOURCE = $(shell find $(PROJECT_SRC_DIR) -name "*.cpp") $(shell find $(PROJECT_SRC_DIR) -name "*.c")
34-
PROJECT_INCLUDE = src
34+
PROJECT_INCLUDE = -Isrc
3535
# application filename will end up as PROJECT_NAME.hex once built
3636
PROJECT_NAME = firmware
3737

@@ -82,7 +82,7 @@ GIT_SCRAPER = ./tools/git_scraper.cpp
8282
# builds source, links with libraries, and constructs the .elf and .hex to be uploaded
8383
build: clean git_scraper
8484
@echo [Building Source]
85-
@$(COMPILER_CPP) $(COMPILE_FLAGS) $(CPP_FLAGS) $(PROJECT_SOURCE) $(LIBRARY_LIB_NAME) $(TEENSY_LIB_NAME) $(LIBRARY_INCLUDE) $(TEENSY_INCLUDE) $(LINKING_FLAGS) -o $(PROJECT_NAME).elf
85+
@$(COMPILER_CPP) $(COMPILE_FLAGS) $(CPP_FLAGS) $(PROJECT_SOURCE) $(PROJECT_INCLUDE) $(LIBRARY_LIB_NAME) $(TEENSY_LIB_NAME) $(LIBRARY_INCLUDE) $(TEENSY_INCLUDE) $(LINKING_FLAGS) -o $(PROJECT_NAME).elf
8686
@echo [Constructing $(PROJECT_NAME).hex]
8787
@$(OBJCOPY) -O ihex -R .eeprom $(PROJECT_NAME).elf $(PROJECT_NAME).hex
8888
@chmod +x $(PROJECT_NAME).hex

src/comms/SDManager.cpp

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#include "SDManager.hpp"
2+
3+
SDManager::SDManager() {
4+
if (!SDinternal.begin()) {
5+
Serial.println("SD_ERROR::SDManager card initialization failed");
6+
// TODO: perhaps there should be a better error handler here??
7+
}
8+
}
9+
10+
int SDManager::open(const char* filepath, int setting) {
11+
// check if exists
12+
if (!exists(filepath)) {
13+
Serial.print("SD_NOTICE::filepath ");
14+
Serial.print(filepath);
15+
Serial.println(" does not exist or contains no file");
16+
return -1;
17+
}
18+
if (file) file.close();
19+
file = SDinternal.open(filepath, setting);
20+
return 0;
21+
}
22+
23+
int SDManager::open(const char* filepath) {
24+
return open(filepath, FILE_WRITE_APPEND);
25+
}
26+
27+
void SDManager::close() {
28+
file.close();
29+
return;
30+
}
31+
32+
int SDManager::touch(const char* filename) {
33+
if (SDinternal.exists(filename)) {
34+
Serial.print("SD_NOTICE::file located at ");
35+
Serial.print(filename);
36+
Serial.println(" already exists");
37+
return -1;
38+
}
39+
if (!SDinternal.open(filename, FILE_WRITE)) {
40+
Serial.print("SD_NOTICE::file located at ");
41+
Serial.print(filename);
42+
Serial.println(" could not be created (directory may not exist)");
43+
return -1;
44+
};
45+
return 0;
46+
}
47+
48+
int SDManager::mkdir(const char* dirname) {
49+
if (!SDinternal.mkdir(dirname)) {
50+
Serial.print("SD_NOTICE::directory ");
51+
Serial.print(dirname);
52+
Serial.println(" could not be created");
53+
return -1;
54+
}
55+
return 0;
56+
}
57+
58+
int SDManager::rm(const char* filename) {
59+
return rm(filename, 0);
60+
}
61+
62+
int SDManager::rm(const char* filename, bool r) {
63+
// check if file or directory
64+
File cur;
65+
if (SDinternal.exists(filename)) cur = SDinternal.open(filename);
66+
else {
67+
Serial.print("SD_NOTICE::file at ");
68+
Serial.print(filename);
69+
Serial.println(" could not be erased (no such file or directory)");
70+
return FILE_NOT_FOUND;
71+
}
72+
73+
if (cur.isDirectory()) {
74+
// attempt to remove dir
75+
if (!r) { // non-recursive erase
76+
if (!SDinternal.rmdir(filename)) {
77+
Serial.print("SD_NOTICE::file at ");
78+
Serial.print(filename);
79+
Serial.println(" could not be erased");
80+
return RM_ERR_DIR_MISC;
81+
}
82+
} else {
83+
// recursive erase
84+
File tmp = cur.openNextFile();
85+
while (tmp) {
86+
char name[SD_DIR_LENGTH];
87+
memset(name, 0, SD_DIR_LENGTH);
88+
memcpy(name, filename, strlen(filename));
89+
if (!(filename[strlen(filename) - 1] == '/')) strcat(name, "/");
90+
strcat(name, tmp.name());
91+
rm(name, 1);
92+
tmp = cur.openNextFile();
93+
}
94+
SDinternal.rmdir(filename);
95+
}
96+
} else {
97+
// attempt to remove file
98+
if (!SDinternal.remove(filename)) {
99+
Serial.print("SD_NOTICE::file at ");
100+
Serial.print(filename);
101+
Serial.println(" could not be erased");
102+
return RM_ERR_FILE_MISC;
103+
}
104+
}
105+
return 0;
106+
}
107+
108+
int SDManager::read(uint8_t* dest, unsigned int len) {
109+
if (!file) {
110+
Serial.println("SD_NOTICE::file cannot be read (no file open)");
111+
return -1;
112+
}
113+
return file.read(dest, len);
114+
}
115+
116+
int SDManager::write(uint8_t* src, unsigned int len) {
117+
if (!file) {
118+
Serial.println("SD_NOTICE::file cannot be written to (no file open)");
119+
return -1;
120+
}
121+
return file.write(src, len);
122+
}
123+
124+
int SDManager::lseek(int offset, int whence) {
125+
int flag = 0;
126+
switch (whence) {
127+
case SEEK_SET:
128+
flag = file.seek(offset);
129+
break;
130+
case SEEK_CUR:
131+
flag = file.seek(file.position() + offset);
132+
break;
133+
case SEEK_END:
134+
flag = file.seek(file.size() + offset);
135+
break;
136+
}
137+
if (flag) return file.position();
138+
else return -1;
139+
}
140+
141+
bool SDManager::exists(const char* filepath) {
142+
return SDinternal.exists(filepath);
143+
}
144+
145+
void SDManager::enumerate_files(const char* root, bool r) {
146+
enumerate_files(root, r, 0);
147+
}
148+
149+
void SDManager::enumerate_files(const char* root, bool r, int tabs) {
150+
// check current
151+
152+
if (!exists(root)) {
153+
Serial.print("SD_NOTICE::file ");
154+
Serial.print(root);
155+
Serial.println(" does not exist");
156+
return;
157+
}
158+
159+
File dir = SDinternal.open(root);
160+
161+
// print current
162+
163+
for (int i = 0; i < tabs; i++) {
164+
Serial.print("-\t");
165+
}
166+
Serial.print(dir.name());
167+
168+
// if not dir, then exit
169+
if (!dir.isDirectory()) {
170+
Serial.println("");
171+
return;
172+
}
173+
174+
Serial.println(" (dir)"); // label directory
175+
176+
// if not recursive, then exit
177+
if ((!r) && tabs > 0) return;
178+
179+
// open tmp file, and loop through all contents of dir
180+
File tmp = dir.openNextFile();
181+
182+
while (tmp) {
183+
// print current file
184+
char cur_path[SD_DIR_LENGTH] = { 0 };
185+
memset(cur_path, 0, SD_DIR_LENGTH);
186+
memcpy(cur_path, root, strlen(root));
187+
if (!(root[strlen(root) - 1] == '/')) strcat(cur_path, "/");
188+
strcat(cur_path, tmp.name());
189+
190+
enumerate_files(cur_path, r, tabs + 1);
191+
192+
// iterate tmp
193+
tmp = dir.openNextFile();
194+
}
195+
tmp.close();
196+
dir.close();
197+
}

src/comms/SDManager.hpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#ifndef SD_WRAP
2+
#define SD_WRAP
3+
4+
#include "../../libraries/SD/SD.h"
5+
#include "../../libraries/SPI/SPI.h"
6+
7+
#define SD_DIR_LENGTH 256
8+
9+
#define FILE_NOT_FOUND 1
10+
#define RM_ERR_DIR_MISC 2
11+
#define RM_ERR_FILE_MISC 3
12+
13+
/// @brief Wrapper for built in SD card
14+
class SDManager {
15+
public:
16+
17+
/// @brief Constructor, initializes SD objects
18+
SDManager();
19+
20+
/// @brief Opens to internal file
21+
/// @param filepath path to file
22+
/// @return 0 on success, -1 on failure
23+
int open(const char* filepath);
24+
25+
/// @brief Opens to internal file, choose open setting from FILE_READ, FILE_WRITE, FILE_WRITE_APPEND
26+
/// @param filepath
27+
/// @param setting
28+
/// @return 0 on success, -1 on failure
29+
/// @note FILE_READ opens from start of file, FILE_WRITE opens at end and truncates file, FILE_WRITE_APPEND opens at end and appends to file
30+
int open(const char* filepath, int setting);
31+
32+
/// @brief Close currently open file
33+
void close();
34+
35+
/// @brief Create new file at filename
36+
/// @param filename path to new file (e.g. /folder/text.txt creates text.txt inside /folder/)
37+
/// @return 0 on success, -1 on failure
38+
int touch(const char* filename);
39+
40+
/// @brief Creates new directory at dirname
41+
/// @param dirname location of new directory (e.g. /folder/newdir creates directory newdir inside /folder/)
42+
/// @return 0 on success, -1 on failure
43+
int mkdir(const char* dirname);
44+
45+
/// @brief Removes file or directory
46+
/// @param filename path to file to remove
47+
/// @param r recursive flag, 1 for recursive removal, 0 for non-recursive
48+
/// @return 0 on success, -1 on failure
49+
/// @note Directory is only removed when empty, or when removed recursively (r==1)
50+
int rm(const char* filename, bool r);
51+
52+
/// @brief Removes file or directory
53+
/// @param filename path to file to remove
54+
/// @return 0 on success, -1 on failure
55+
/// @note Overload for removing files by default, sets recursive flag to 0
56+
int rm(const char* filename);
57+
58+
/// @brief Reads bytes from file into dest at file location
59+
/// @param dest destination buffer for data
60+
/// @param len number of bytes to read
61+
/// @return number of bytes read
62+
int read(uint8_t* dest, unsigned int len);
63+
64+
/// @brief Writes bytes from src into file at file location
65+
/// @param src source buffer
66+
/// @param len number of bytes to write
67+
/// @return number of bytes written
68+
int write(uint8_t* src, unsigned int len);
69+
70+
/// @brief Changes location in file based on offset and whence value
71+
/// @param offset amount to change location by
72+
/// @param whence setting for lseek configuration (SEEK_SET, SEEK_CUR, SEEK_END)
73+
/// @return location in file after seek, or -1 on failure
74+
/// @note SEEK_SET sets location to offset, SEEK_CUR sets location to location + offset, SEEK_END sets location to file size + offset
75+
int lseek(int offset, int whence);
76+
77+
/// @brief Checks if file at filepath exists
78+
/// @param filepath path to file
79+
/// @return true if exists, false if not
80+
bool exists(const char* filepath);
81+
82+
/// @brief Prints all files present in directory root
83+
/// @param root root directory to enumerate
84+
/// @param r recursive flag, set true to print contents of all subdirectories
85+
void enumerate_files(const char* root, bool r);
86+
87+
private:
88+
89+
/// @brief Prints all files present in directory root
90+
/// @param root root directory to enumerate
91+
/// @param r recursive flag, set true to print contents of all subdirectories
92+
/// @param tabs number of tabs to print (used internally for inner dir printing)
93+
void enumerate_files(const char* root, bool r, int tabs);
94+
95+
/// @brief Internal instance of SDClass object used by Teensy
96+
SDClass SDinternal;
97+
98+
/// @brief Internal File object that represents currently opened file on SD card
99+
File file;
100+
};
101+
102+
#endif

src/main.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "sensors/RefSystem.hpp"
1515
#include "sensors/d200.hpp"
1616
#include "sensors/ACS712.hpp"
17+
#include "comms/SDManager.hpp"
1718

1819
#include <TeensyDebug.h>
1920

@@ -86,7 +87,6 @@ int main() {
8687

8788
Serial.begin(115200); // the serial monitor is actually always active (for debug use Serial.println & tycmd)
8889
debug.begin(SerialUSB1);
89-
9090
print_logo();
9191

9292
// Execute setup functions
@@ -104,7 +104,6 @@ int main() {
104104
uint8_t packet_subsection_sizes[MAX_CONFIG_PACKETS] = { 0 };
105105
CommsPacket config_packets[MAX_CONFIG_PACKETS];
106106
// Config config
107-
108107
Serial.println("Configuring...");
109108
while (!config_layer.is_configured()) {
110109
comms.ping();

src/utils/profiler.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#define PROF_MAX_SECTIONS 4 // max number of active profiling sections
1010
#define PROF_MAX_NAME 16 // max length of section name
11-
#define PROF_MAX_TIMES (1 << 20) // max number of start/end times per section
11+
#define PROF_MAX_TIMES (60000) // max number of start/end times per section
1212

1313
/// @brief Object for profiling sections of code.
1414
struct Profiler {

0 commit comments

Comments
 (0)