Optimize SD card reader, sorting (#15395)
This commit is contained in:
parent
1834d86df5
commit
2277c6dffc
5 changed files with 295 additions and 220 deletions
|
@ -1002,14 +1002,14 @@ namespace ExtUI {
|
||||||
|
|
||||||
void FileList::upDir() {
|
void FileList::upDir() {
|
||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
card.updir();
|
card.cdup();
|
||||||
num_files = 0xFFFF;
|
num_files = 0xFFFF;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileList::changeDir(const char * const dirname) {
|
void FileList::changeDir(const char * const dirname) {
|
||||||
#if ENABLED(SDSUPPORT)
|
#if ENABLED(SDSUPPORT)
|
||||||
card.chdir(dirname);
|
card.cd(dirname);
|
||||||
num_files = 0xFFFF;
|
num_files = 0xFFFF;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,13 +246,13 @@ void process_lcd_p_command(const char* command) {
|
||||||
// Find the name of the file to print.
|
// Find the name of the file to print.
|
||||||
// It's needed to echo the PRINTFILE option.
|
// It's needed to echo the PRINTFILE option.
|
||||||
// The {S:L} command should've ensured the SD card was mounted.
|
// The {S:L} command should've ensured the SD card was mounted.
|
||||||
card.getfilename(atoi(command));
|
card.selectFileByIndex(atoi(command));
|
||||||
|
|
||||||
// There may be a difference in how V1 and V2 LCDs handle subdirectory
|
// There may be a difference in how V1 and V2 LCDs handle subdirectory
|
||||||
// prints. Investigate more. This matches the V1 motion controller actions
|
// prints. Investigate more. This matches the V1 motion controller actions
|
||||||
// but the V2 LCD switches to "print" mode on {SYS:DIR} response.
|
// but the V2 LCD switches to "print" mode on {SYS:DIR} response.
|
||||||
if (card.flag.filenameIsDir) {
|
if (card.flag.filenameIsDir) {
|
||||||
card.chdir(card.filename);
|
card.cd(card.filename);
|
||||||
write_to_lcd_P(PSTR("{SYS:DIR}"));
|
write_to_lcd_P(PSTR("{SYS:DIR}"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -309,7 +309,7 @@ void process_lcd_s_command(const char* command) {
|
||||||
char message_buffer[MAX_CURLY_COMMAND];
|
char message_buffer[MAX_CURLY_COMMAND];
|
||||||
uint16_t file_count = card.get_num_Files();
|
uint16_t file_count = card.get_num_Files();
|
||||||
for (uint16_t i = 0; i < file_count; i++) {
|
for (uint16_t i = 0; i < file_count; i++) {
|
||||||
card.getfilename(i);
|
card.selectFileByIndex(i);
|
||||||
sprintf_P(message_buffer, card.flag.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.longest_filename());
|
sprintf_P(message_buffer, card.flag.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.longest_filename());
|
||||||
write_to_lcd(message_buffer);
|
write_to_lcd(message_buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void lcd_sd_updir() {
|
void lcd_sd_updir() {
|
||||||
ui.encoderPosition = card.updir() ? ENCODER_STEPS_PER_MENU_ITEM : 0;
|
ui.encoderPosition = card.cdup() ? ENCODER_STEPS_PER_MENU_ITEM : 0;
|
||||||
encoderTopLine = 0;
|
encoderTopLine = 0;
|
||||||
screen_changed = true;
|
screen_changed = true;
|
||||||
ui.refresh();
|
ui.refresh();
|
||||||
|
@ -115,7 +115,7 @@ class MenuItem_sdfile {
|
||||||
class MenuItem_sdfolder {
|
class MenuItem_sdfolder {
|
||||||
public:
|
public:
|
||||||
static void action(CardReader &theCard) {
|
static void action(CardReader &theCard) {
|
||||||
card.chdir(theCard.filename);
|
card.cd(theCard.filename);
|
||||||
encoderTopLine = 0;
|
encoderTopLine = 0;
|
||||||
ui.encoderPosition = 2 * (ENCODER_STEPS_PER_MENU_ITEM);
|
ui.encoderPosition = 2 * (ENCODER_STEPS_PER_MENU_ITEM);
|
||||||
screen_changed = true;
|
screen_changed = true;
|
||||||
|
|
|
@ -62,6 +62,7 @@ SdFile CardReader::root, CardReader::workDir, CardReader::workDirParents[MAX_DIR
|
||||||
uint8_t CardReader::workDirDepth;
|
uint8_t CardReader::workDirDepth;
|
||||||
|
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
|
|
||||||
uint16_t CardReader::sort_count;
|
uint16_t CardReader::sort_count;
|
||||||
#if ENABLED(SDSORT_GCODE)
|
#if ENABLED(SDSORT_GCODE)
|
||||||
bool CardReader::sort_alpha;
|
bool CardReader::sort_alpha;
|
||||||
|
@ -78,6 +79,7 @@ uint8_t CardReader::workDirDepth;
|
||||||
#if ENABLED(SDSORT_USES_RAM)
|
#if ENABLED(SDSORT_USES_RAM)
|
||||||
|
|
||||||
#if ENABLED(SDSORT_CACHE_NAMES)
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
||||||
|
uint16_t CardReader::nrFiles; // Cached total file count
|
||||||
#if ENABLED(SDSORT_DYNAMIC_RAM)
|
#if ENABLED(SDSORT_DYNAMIC_RAM)
|
||||||
char **CardReader::sortshort, **CardReader::sortnames;
|
char **CardReader::sortshort, **CardReader::sortnames;
|
||||||
#else
|
#else
|
||||||
|
@ -94,6 +96,7 @@ uint8_t CardReader::workDirDepth;
|
||||||
#elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
|
#elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
|
||||||
uint8_t CardReader::isDir[(SDSORT_LIMIT+7)>>3];
|
uint8_t CardReader::isDir[(SDSORT_LIMIT+7)>>3];
|
||||||
#endif
|
#endif
|
||||||
|
#define IS_DIR(n) TEST(isDir[(n) >> 3], (n) & 0x07)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SDSORT_USES_RAM
|
#endif // SDSORT_USES_RAM
|
||||||
|
@ -110,10 +113,6 @@ char CardReader::proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
||||||
|
|
||||||
uint32_t CardReader::filesize, CardReader::sdpos;
|
uint32_t CardReader::filesize, CardReader::sdpos;
|
||||||
|
|
||||||
LsAction CardReader::lsAction; //stored for recursion.
|
|
||||||
uint16_t CardReader::nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
|
|
||||||
char *CardReader::diveDirName;
|
|
||||||
|
|
||||||
CardReader::CardReader() {
|
CardReader::CardReader() {
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
sort_count = 0;
|
sort_count = 0;
|
||||||
|
@ -138,7 +137,10 @@ CardReader::CardReader() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
char *createFilename(char *buffer, const dir_t &p) {
|
//
|
||||||
|
// Get a DOS 8.3 filename in its useful form
|
||||||
|
//
|
||||||
|
char *createFilename(char * const buffer, const dir_t &p) {
|
||||||
char *pos = buffer;
|
char *pos = buffer;
|
||||||
for (uint8_t i = 0; i < 11; i++) {
|
for (uint8_t i = 0; i < 11; i++) {
|
||||||
if (p.name[i] == ' ') continue;
|
if (p.name[i] == ' ') continue;
|
||||||
|
@ -149,24 +151,78 @@ char *createFilename(char *buffer, const dir_t &p) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//
|
||||||
* Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
|
// Return 'true' if the item is a folder or G-code file
|
||||||
* LS_Count - Add +1 to nrFiles for every file within the parent
|
//
|
||||||
* LS_GetFilename - Get the filename of the file indexed by nrFile_index
|
bool CardReader::is_dir_or_gcode(const dir_t &p) {
|
||||||
* LS_SerialPrint - Print the full path and size of each file to serial output
|
uint8_t pn0 = p.name[0];
|
||||||
*/
|
|
||||||
|
|
||||||
uint16_t nrFile_index;
|
if ( pn0 == DIR_NAME_FREE || pn0 == DIR_NAME_DELETED // Clear or Deleted entry
|
||||||
|
|| pn0 == '.' || longFilename[0] == '.' // Hidden file
|
||||||
|
|| !DIR_IS_FILE_OR_SUBDIR(&p) // Not a File or Directory
|
||||||
|
|| (p.attributes & DIR_ATT_HIDDEN) // Hidden by attribute
|
||||||
|
) return false;
|
||||||
|
|
||||||
void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=nullptr*/) {
|
flag.filenameIsDir = DIR_IS_SUBDIR(&p); // We know it's a File or Folder
|
||||||
|
|
||||||
|
return (
|
||||||
|
flag.filenameIsDir // All Directories are ok
|
||||||
|
|| (p.name[8] == 'G' && p.name[9] != '~') // Non-backup *.G* files are accepted
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the number of (compliant) items in the folder
|
||||||
|
//
|
||||||
|
int CardReader::countItems(SdFile dir) {
|
||||||
dir_t p;
|
dir_t p;
|
||||||
uint8_t cnt = 0;
|
int c = 0;
|
||||||
|
while (dir.readDir(&p, longFilename) > 0)
|
||||||
|
c += is_dir_or_gcode(p);
|
||||||
|
|
||||||
// Read the next entry from a directory
|
#if ENABLED(SDCARD_SORT_ALPHA) && SDSORT_USES_RAM && SDSORT_CACHE_NAMES
|
||||||
|
nrFiles = c;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get file/folder info for an item by index
|
||||||
|
//
|
||||||
|
void CardReader::selectByIndex(SdFile dir, const uint8_t index) {
|
||||||
|
dir_t p;
|
||||||
|
for (uint8_t cnt = 0; dir.readDir(&p, longFilename) > 0;) {
|
||||||
|
if (is_dir_or_gcode(p)) {
|
||||||
|
if (cnt == index) {
|
||||||
|
createFilename(filename, p);
|
||||||
|
return; // 0 based index
|
||||||
|
}
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get file/folder info for an item by name
|
||||||
|
//
|
||||||
|
void CardReader::selectByName(SdFile dir, const char * const match) {
|
||||||
|
dir_t p;
|
||||||
|
for (uint8_t cnt = 0; dir.readDir(&p, longFilename) > 0; cnt++) {
|
||||||
|
if (is_dir_or_gcode(p)) {
|
||||||
|
createFilename(filename, p);
|
||||||
|
if (strcasecmp(match, filename) == 0) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Recursive method to list all files within a folder
|
||||||
|
//
|
||||||
|
void CardReader::printListing(SdFile parent, const char * const prepend/*=nullptr*/) {
|
||||||
|
dir_t p;
|
||||||
while (parent.readDir(&p, longFilename) > 0) {
|
while (parent.readDir(&p, longFilename) > 0) {
|
||||||
|
if (DIR_IS_SUBDIR(&p)) {
|
||||||
// If the entry is a directory and the action is LS_SerialPrint
|
|
||||||
if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
|
|
||||||
|
|
||||||
// Get the short name for the item, which we know is a folder
|
// Get the short name for the item, which we know is a folder
|
||||||
char dosFilename[FILENAME_LENGTH];
|
char dosFilename[FILENAME_LENGTH];
|
||||||
|
@ -188,68 +244,38 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
||||||
|
|
||||||
// Get a new directory object using the full path
|
// Get a new directory object using the full path
|
||||||
// and dive recursively into it.
|
// and dive recursively into it.
|
||||||
SdFile dir;
|
SdFile child;
|
||||||
if (!dir.open(&parent, dosFilename, O_READ)) {
|
if (!child.open(&parent, dosFilename, O_READ)) {
|
||||||
if (lsAction == LS_SerialPrint) {
|
SERIAL_ECHO_START();
|
||||||
SERIAL_ECHO_START();
|
SERIAL_ECHOLNPAIR(MSG_SD_CANT_OPEN_SUBDIR, dosFilename);
|
||||||
SERIAL_ECHOLNPAIR(MSG_SD_CANT_OPEN_SUBDIR, dosFilename);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lsDive(path, dir);
|
printListing(child, path);
|
||||||
// close() is done automatically by destructor of SdFile
|
// close() is done automatically by destructor of SdFile
|
||||||
}
|
}
|
||||||
else {
|
else if (is_dir_or_gcode(p)) {
|
||||||
uint8_t pn0 = p.name[0];
|
createFilename(filename, p);
|
||||||
if (pn0 == DIR_NAME_FREE) break;
|
if (prepend) SERIAL_ECHO(prepend);
|
||||||
if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
|
SERIAL_ECHO(filename);
|
||||||
if (longFilename[0] == '.') continue;
|
SERIAL_CHAR(' ');
|
||||||
|
SERIAL_ECHOLN(p.fileSize);
|
||||||
if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
|
|
||||||
|
|
||||||
flag.filenameIsDir = DIR_IS_SUBDIR(&p);
|
|
||||||
|
|
||||||
if (!flag.filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
|
|
||||||
|
|
||||||
switch (lsAction) { // 1 based file count
|
|
||||||
case LS_Count:
|
|
||||||
nrFiles++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LS_SerialPrint:
|
|
||||||
createFilename(filename, p);
|
|
||||||
if (prepend) SERIAL_ECHO(prepend);
|
|
||||||
SERIAL_ECHO(filename);
|
|
||||||
SERIAL_CHAR(' ');
|
|
||||||
SERIAL_ECHOLN(p.fileSize);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LS_GetFilename:
|
|
||||||
createFilename(filename, p);
|
|
||||||
if (match != nullptr) {
|
|
||||||
if (strcasecmp(match, filename) == 0) return;
|
|
||||||
}
|
|
||||||
else if (cnt == nrFile_index) return; // 0 based index
|
|
||||||
cnt++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} // while readDir
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// List all files on the SD card
|
||||||
|
//
|
||||||
void CardReader::ls() {
|
void CardReader::ls() {
|
||||||
lsAction = LS_SerialPrint;
|
|
||||||
root.rewind();
|
root.rewind();
|
||||||
lsDive(nullptr, root);
|
printListing(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
||||||
|
|
||||||
/**
|
//
|
||||||
* Get a long pretty path based on a DOS 8.3 path
|
// Get a long pretty path based on a DOS 8.3 path
|
||||||
*/
|
//
|
||||||
void CardReader::printLongPath(char *path) {
|
void CardReader::printLongPath(char * const path) {
|
||||||
lsAction = LS_GetFilename;
|
|
||||||
|
|
||||||
int i, pathLen = strlen(path);
|
int i, pathLen = strlen(path);
|
||||||
|
|
||||||
|
@ -275,7 +301,7 @@ void CardReader::ls() {
|
||||||
|
|
||||||
// Find the item, setting the long filename
|
// Find the item, setting the long filename
|
||||||
diveDir.rewind();
|
diveDir.rewind();
|
||||||
lsDive(nullptr, diveDir, segment);
|
selectByName(diveDir, segment);
|
||||||
|
|
||||||
// Print /LongNamePart to serial output
|
// Print /LongNamePart to serial output
|
||||||
SERIAL_CHAR('/');
|
SERIAL_CHAR('/');
|
||||||
|
@ -305,16 +331,16 @@ void CardReader::ls() {
|
||||||
|
|
||||||
#endif // LONG_FILENAME_HOST_SUPPORT
|
#endif // LONG_FILENAME_HOST_SUPPORT
|
||||||
|
|
||||||
/**
|
//
|
||||||
* Echo the DOS 8.3 filename (and long filename, if any)
|
// Echo the DOS 8.3 filename (and long filename, if any)
|
||||||
*/
|
//
|
||||||
void CardReader::printFilename() {
|
void CardReader::printFilename() {
|
||||||
if (file.isOpen()) {
|
if (file.isOpen()) {
|
||||||
char dosFilename[FILENAME_LENGTH];
|
char dosFilename[FILENAME_LENGTH];
|
||||||
file.getDosName(dosFilename);
|
file.getDosName(dosFilename);
|
||||||
SERIAL_ECHO(dosFilename);
|
SERIAL_ECHO(dosFilename);
|
||||||
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
||||||
getfilename(0, dosFilename);
|
selectFileByName(dosFilename);
|
||||||
if (longFilename[0]) {
|
if (longFilename[0]) {
|
||||||
SERIAL_ECHO(' ');
|
SERIAL_ECHO(' ');
|
||||||
SERIAL_ECHO(longFilename);
|
SERIAL_ECHO(longFilename);
|
||||||
|
@ -339,10 +365,7 @@ void CardReader::mount() {
|
||||||
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
|
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
|
||||||
&& !sd2card.init(SPI_SPEED, LCD_SDSS)
|
&& !sd2card.init(SPI_SPEED, LCD_SDSS)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) SERIAL_ECHO_MSG(MSG_SD_INIT_FAIL);
|
||||||
//if (!sd2card.init(SPI_HALF_SPEED,SDSS))
|
|
||||||
SERIAL_ECHO_MSG(MSG_SD_INIT_FAIL);
|
|
||||||
}
|
|
||||||
else if (!volume.init(&sd2card))
|
else if (!volume.init(&sd2card))
|
||||||
SERIAL_ERROR_MSG(MSG_SD_VOL_INIT_FAIL);
|
SERIAL_ERROR_MSG(MSG_SD_VOL_INIT_FAIL);
|
||||||
else if (!root.openRoot(&volume))
|
else if (!root.openRoot(&volume))
|
||||||
|
@ -354,7 +377,7 @@ void CardReader::mount() {
|
||||||
settings.first_load();
|
settings.first_load();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
setroot();
|
cdroot();
|
||||||
|
|
||||||
ui.refresh();
|
ui.refresh();
|
||||||
}
|
}
|
||||||
|
@ -401,26 +424,32 @@ void CardReader::openLogFile(char * const path) {
|
||||||
openFile(path, false);
|
openFile(path, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendAtom(SdFile &file, char *& dst, uint8_t &cnt) {
|
//
|
||||||
file.getDosName(dst);
|
// Get the root-relative DOS path of the selected file
|
||||||
while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
|
//
|
||||||
if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
|
void CardReader::getAbsFilename(char *dst) {
|
||||||
}
|
*dst++ = '/';
|
||||||
|
|
||||||
void CardReader::getAbsFilename(char *t) {
|
|
||||||
*t++ = '/'; // Root folder
|
|
||||||
uint8_t cnt = 1;
|
uint8_t cnt = 1;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < workDirDepth; i++) // Loop to current work dir
|
auto appendAtom = [&](SdFile &file) {
|
||||||
appendAtom(workDirParents[i], t, cnt);
|
file.getDosName(dst);
|
||||||
|
while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
|
||||||
|
if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < workDirDepth; i++) // Loop down to current work dir
|
||||||
|
appendAtom(workDirParents[i]);
|
||||||
|
|
||||||
if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH) - 1) { // Leave room for filename and nul
|
if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH) - 1) { // Leave room for filename and nul
|
||||||
appendAtom(file, t, cnt);
|
appendAtom(file);
|
||||||
--t;
|
--dst;
|
||||||
}
|
}
|
||||||
*t = '\0';
|
*dst = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Open a file by DOS path - for read or write
|
||||||
|
//
|
||||||
void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) {
|
void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) {
|
||||||
|
|
||||||
if (!isMounted()) return;
|
if (!isMounted()) return;
|
||||||
|
@ -472,7 +501,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
|
||||||
SERIAL_ECHOLNPAIR(MSG_SD_FILE_OPENED, fname, MSG_SD_SIZE, filesize);
|
SERIAL_ECHOLNPAIR(MSG_SD_FILE_OPENED, fname, MSG_SD_SIZE, filesize);
|
||||||
SERIAL_ECHOLNPGM(MSG_SD_FILE_SELECTED);
|
SERIAL_ECHOLNPGM(MSG_SD_FILE_SELECTED);
|
||||||
|
|
||||||
getfilename(0, fname);
|
selectFileByName(fname);
|
||||||
ui.set_status(longFilename[0] ? longFilename : fname);
|
ui.set_status(longFilename[0] ? longFilename : fname);
|
||||||
//if (longFilename[0]) {
|
//if (longFilename[0]) {
|
||||||
// SERIAL_ECHOPAIR(MSG_SD_FILE_LONG_NAME, longFilename);
|
// SERIAL_ECHOPAIR(MSG_SD_FILE_LONG_NAME, longFilename);
|
||||||
|
@ -486,7 +515,7 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
|
||||||
SERIAL_ECHOLNPAIR(MSG_SD_OPEN_FILE_FAIL, fname, ".");
|
SERIAL_ECHOLNPAIR(MSG_SD_OPEN_FILE_FAIL, fname, ".");
|
||||||
else {
|
else {
|
||||||
flag.saving = true;
|
flag.saving = true;
|
||||||
getfilename(0, fname);
|
selectFileByName(fname);
|
||||||
#if ENABLED(EMERGENCY_PARSER)
|
#if ENABLED(EMERGENCY_PARSER)
|
||||||
emergency_parser.disable();
|
emergency_parser.disable();
|
||||||
#endif
|
#endif
|
||||||
|
@ -496,6 +525,9 @@ void CardReader::openFile(char * const path, const bool read, const bool subcall
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Delete a file by name in the working directory
|
||||||
|
//
|
||||||
void CardReader::removeFile(const char * const name) {
|
void CardReader::removeFile(const char * const name) {
|
||||||
if (!isMounted()) return;
|
if (!isMounted()) return;
|
||||||
|
|
||||||
|
@ -527,7 +559,7 @@ void CardReader::report_status() {
|
||||||
SERIAL_ECHOLNPGM(MSG_SD_NOT_PRINTING);
|
SERIAL_ECHOLNPGM(MSG_SD_NOT_PRINTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::write_command(char *buf) {
|
void CardReader::write_command(char * const buf) {
|
||||||
char* begin = buf;
|
char* begin = buf;
|
||||||
char* npos = nullptr;
|
char* npos = nullptr;
|
||||||
char* end = buf + strlen(buf) - 1;
|
char* end = buf + strlen(buf) - 1;
|
||||||
|
@ -584,7 +616,7 @@ void CardReader::checkautostart() {
|
||||||
|
|
||||||
void CardReader::beginautostart() {
|
void CardReader::beginautostart() {
|
||||||
autostart_index = 0;
|
autostart_index = 0;
|
||||||
setroot();
|
cdroot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::closefile(const bool store_location) {
|
void CardReader::closefile(const bool store_location) {
|
||||||
|
@ -602,38 +634,42 @@ void CardReader::closefile(const bool store_location) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//
|
||||||
* Get the name of a file in the current directory by index
|
// Get info for a file in the working directory by index
|
||||||
* with optional name to match.
|
//
|
||||||
*/
|
void CardReader::selectFileByIndex(const uint16_t nr) {
|
||||||
void CardReader::getfilename(uint16_t nr, const char * const match/*=nullptr*/) {
|
|
||||||
#if ENABLED(SDSORT_CACHE_NAMES)
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
||||||
if (match != nullptr) {
|
|
||||||
while (nr < sort_count) {
|
|
||||||
if (strcasecmp(match, sortshort[nr]) == 0) break;
|
|
||||||
nr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nr < sort_count) {
|
if (nr < sort_count) {
|
||||||
strcpy(filename, sortshort[nr]);
|
strcpy(filename, sortshort[nr]);
|
||||||
strcpy(longFilename, sortnames[nr]);
|
strcpy(longFilename, sortnames[nr]);
|
||||||
flag.filenameIsDir = TEST(isDir[nr>>3], nr & 0x07);
|
flag.filenameIsDir = IS_DIR(nr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif // SDSORT_CACHE_NAMES
|
#endif
|
||||||
lsAction = LS_GetFilename;
|
|
||||||
nrFile_index = nr;
|
|
||||||
workDir.rewind();
|
workDir.rewind();
|
||||||
lsDive(nullptr, workDir, match);
|
selectByIndex(workDir, nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get info for a file in the working directory by DOS name
|
||||||
|
//
|
||||||
|
void CardReader::selectFileByName(const char * const match) {
|
||||||
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
||||||
|
for (int nr = 0; nr < sort_count; nr++)
|
||||||
|
if (strcasecmp(match, sortshort[nr]) == 0) {
|
||||||
|
strcpy(filename, sortshort[nr]);
|
||||||
|
strcpy(longFilename, sortnames[nr]);
|
||||||
|
flag.filenameIsDir = IS_DIR(nr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
workDir.rewind();
|
||||||
|
selectByName(workDir, match);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t CardReader::countFilesInWorkDir() {
|
uint16_t CardReader::countFilesInWorkDir() {
|
||||||
lsAction = LS_Count;
|
|
||||||
nrFiles = 0;
|
|
||||||
workDir.rewind();
|
workDir.rewind();
|
||||||
lsDive(nullptr, workDir);
|
return countItems(workDir);
|
||||||
//SERIAL_ECHOLN(nrFiles);
|
|
||||||
return nrFiles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -650,11 +686,11 @@ const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, con
|
||||||
static SdFile newDir1, newDir2;
|
static SdFile newDir1, newDir2;
|
||||||
SdFile *sub = &newDir1, *startDir;
|
SdFile *sub = &newDir1, *startDir;
|
||||||
|
|
||||||
const char *dirname_start = path;
|
const char *item_name_adr = path;
|
||||||
if (path[0] == '/') {
|
if (path[0] == '/') {
|
||||||
curDir = &root;
|
curDir = &root;
|
||||||
workDirDepth = 0;
|
workDirDepth = 0;
|
||||||
dirname_start++;
|
item_name_adr++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
curDir = &workDir;
|
curDir = &workDir;
|
||||||
|
@ -662,15 +698,15 @@ const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, con
|
||||||
startDir = curDir;
|
startDir = curDir;
|
||||||
|
|
||||||
// Start dive
|
// Start dive
|
||||||
while (dirname_start) {
|
while (item_name_adr) {
|
||||||
// Find next sub
|
// Find next sub
|
||||||
char * const dirname_end = strchr(dirname_start, '/');
|
char * const name_end = strchr(item_name_adr, '/');
|
||||||
if (dirname_end <= dirname_start) break;
|
if (name_end <= item_name_adr) break;
|
||||||
|
|
||||||
// Set subDirName
|
// Set subDirName
|
||||||
const uint8_t len = dirname_end - dirname_start;
|
const uint8_t len = name_end - item_name_adr;
|
||||||
char dosSubdirname[len + 1];
|
char dosSubdirname[len + 1];
|
||||||
strncpy(dosSubdirname, dirname_start, len);
|
strncpy(dosSubdirname, item_name_adr, len);
|
||||||
dosSubdirname[len] = 0;
|
dosSubdirname[len] = 0;
|
||||||
|
|
||||||
if (echo) SERIAL_ECHOLN(dosSubdirname);
|
if (echo) SERIAL_ECHOLN(dosSubdirname);
|
||||||
|
@ -693,13 +729,13 @@ const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, con
|
||||||
// Point sub pointer to unused newDir
|
// Point sub pointer to unused newDir
|
||||||
sub = (curDir != &newDir1) ? &newDir1 : &newDir2;
|
sub = (curDir != &newDir1) ? &newDir1 : &newDir2;
|
||||||
|
|
||||||
// dirname_start point to next sub
|
// item_name_adr point to next sub
|
||||||
dirname_start = dirname_end + 1;
|
item_name_adr = name_end + 1;
|
||||||
}
|
}
|
||||||
return dirname_start;
|
return item_name_adr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::chdir(const char * relpath) {
|
void CardReader::cd(const char * relpath) {
|
||||||
SdFile newDir;
|
SdFile newDir;
|
||||||
SdFile *parent = workDir.isOpen() ? &workDir : &root;
|
SdFile *parent = workDir.isOpen() ? &workDir : &root;
|
||||||
|
|
||||||
|
@ -718,7 +754,7 @@ void CardReader::chdir(const char * relpath) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t CardReader::updir() {
|
int8_t CardReader::cdup() {
|
||||||
if (workDirDepth > 0) { // At least 1 dir has been saved
|
if (workDirDepth > 0) { // At least 1 dir has been saved
|
||||||
workDir = --workDirDepth ? workDirParents[workDirDepth - 1] : root; // Use parent, or root if none
|
workDir = --workDirDepth ? workDirParents[workDirDepth - 1] : root; // Use parent, or root if none
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
|
@ -729,7 +765,7 @@ int8_t CardReader::updir() {
|
||||||
return workDirDepth;
|
return workDirDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardReader::setroot() {
|
void CardReader::cdroot() {
|
||||||
workDir = root;
|
workDir = root;
|
||||||
flag.workDirIsRoot = true;
|
flag.workDirIsRoot = true;
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
|
@ -740,10 +776,10 @@ void CardReader::setroot() {
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of a file in the current directory by sort-index
|
* Get the name of a file in the working directory by sort-index
|
||||||
*/
|
*/
|
||||||
void CardReader::getfilename_sorted(const uint16_t nr) {
|
void CardReader::getfilename_sorted(const uint16_t nr) {
|
||||||
getfilename(
|
selectFileByIndex(
|
||||||
#if ENABLED(SDSORT_GCODE)
|
#if ENABLED(SDSORT_GCODE)
|
||||||
sort_alpha &&
|
sort_alpha &&
|
||||||
#endif
|
#endif
|
||||||
|
@ -757,7 +793,7 @@ void CardReader::setroot() {
|
||||||
#define SET_SORTNAME(I) (sortnames[I] = strdup(longest_filename()))
|
#define SET_SORTNAME(I) (sortnames[I] = strdup(longest_filename()))
|
||||||
#if ENABLED(SDSORT_CACHE_NAMES)
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
||||||
// When caching also store the short name, since
|
// When caching also store the short name, since
|
||||||
// we're replacing the getfilename() behavior.
|
// we're replacing the selectFileByIndex() behavior.
|
||||||
#define SET_SORTSHORT(I) (sortshort[I] = strdup(filename))
|
#define SET_SORTSHORT(I) (sortshort[I] = strdup(filename))
|
||||||
#else
|
#else
|
||||||
#define SET_SORTSHORT(I) NOOP
|
#define SET_SORTSHORT(I) NOOP
|
||||||
|
@ -854,7 +890,7 @@ void CardReader::setroot() {
|
||||||
i);
|
i);
|
||||||
// If using RAM then read all filenames now.
|
// If using RAM then read all filenames now.
|
||||||
#if ENABLED(SDSORT_USES_RAM)
|
#if ENABLED(SDSORT_USES_RAM)
|
||||||
getfilename(i);
|
selectFileByIndex(i);
|
||||||
SET_SORTNAME(i);
|
SET_SORTNAME(i);
|
||||||
SET_SORTSHORT(i);
|
SET_SORTSHORT(i);
|
||||||
// char out[30];
|
// char out[30];
|
||||||
|
@ -871,8 +907,17 @@ void CardReader::setroot() {
|
||||||
// Bubble Sort
|
// Bubble Sort
|
||||||
for (uint16_t i = fileCnt; --i;) {
|
for (uint16_t i = fileCnt; --i;) {
|
||||||
bool didSwap = false;
|
bool didSwap = false;
|
||||||
|
uint8_t o1 = sort_order[0];
|
||||||
|
#if DISABLED(SDSORT_USES_RAM)
|
||||||
|
selectFileByIndex(o1); // Pre-fetch the first entry and save it
|
||||||
|
strcpy(name1, longest_filename()); // so the loop only needs one fetch
|
||||||
|
#if HAS_FOLDER_SORTING
|
||||||
|
bool dir1 = flag.filenameIsDir;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
for (uint16_t j = 0; j < i; ++j) {
|
for (uint16_t j = 0; j < i; ++j) {
|
||||||
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
|
const uint16_t o2 = sort_order[j + 1];
|
||||||
|
|
||||||
// Compare names from the array or just the two buffered names
|
// Compare names from the array or just the two buffered names
|
||||||
#if ENABLED(SDSORT_USES_RAM)
|
#if ENABLED(SDSORT_USES_RAM)
|
||||||
|
@ -884,12 +929,7 @@ void CardReader::setroot() {
|
||||||
#if HAS_FOLDER_SORTING
|
#if HAS_FOLDER_SORTING
|
||||||
#if ENABLED(SDSORT_USES_RAM)
|
#if ENABLED(SDSORT_USES_RAM)
|
||||||
// Folder sorting needs an index and bit to test for folder-ness.
|
// Folder sorting needs an index and bit to test for folder-ness.
|
||||||
const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
|
#define _SORT_CMP_DIR(fs) IS_DIR(o1) == IS_DIR(o2) ? _SORT_CMP_NODIR() : IS_DIR(fs > 0 ? o1 : o2)
|
||||||
ind2 = o2 >> 3, bit2 = o2 & 0x07;
|
|
||||||
#define _SORT_CMP_DIR(fs) \
|
|
||||||
(((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
|
|
||||||
? _SORT_CMP_NODIR() \
|
|
||||||
: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
|
|
||||||
#else
|
#else
|
||||||
#define _SORT_CMP_DIR(fs) ((dir1 == flag.filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
|
#define _SORT_CMP_DIR(fs) ((dir1 == flag.filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
|
||||||
#endif
|
#endif
|
||||||
|
@ -898,13 +938,9 @@ void CardReader::setroot() {
|
||||||
// The most economical method reads names as-needed
|
// The most economical method reads names as-needed
|
||||||
// throughout the loop. Slow if there are many.
|
// throughout the loop. Slow if there are many.
|
||||||
#if DISABLED(SDSORT_USES_RAM)
|
#if DISABLED(SDSORT_USES_RAM)
|
||||||
getfilename(o1);
|
selectFileByIndex(o2);
|
||||||
strcpy(name1, longest_filename()); // save (or getfilename below will trounce it)
|
const bool dir2 = flag.filenameIsDir;
|
||||||
#if HAS_FOLDER_SORTING
|
char * const name2 = longest_filename(); // use the string in-place
|
||||||
bool dir1 = flag.filenameIsDir;
|
|
||||||
#endif
|
|
||||||
getfilename(o2);
|
|
||||||
char *name2 = longest_filename(); // use the string in-place
|
|
||||||
#endif // !SDSORT_USES_RAM
|
#endif // !SDSORT_USES_RAM
|
||||||
|
|
||||||
// Sort the current pair according to settings.
|
// Sort the current pair according to settings.
|
||||||
|
@ -919,10 +955,22 @@ void CardReader::setroot() {
|
||||||
_SORT_CMP_NODIR()
|
_SORT_CMP_NODIR()
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
|
// Reorder the index, indicate that sorting happened
|
||||||
|
// Note that the next o1 will be the current o1. No new fetch needed.
|
||||||
sort_order[j] = o2;
|
sort_order[j] = o2;
|
||||||
sort_order[j + 1] = o1;
|
sort_order[j + 1] = o1;
|
||||||
didSwap = true;
|
didSwap = true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// The next o1 is the current o2. No new fetch needed.
|
||||||
|
o1 = o2;
|
||||||
|
#if DISABLED(SDSORT_USES_RAM)
|
||||||
|
#if HAS_FOLDER_SORTING
|
||||||
|
dir1 = dir2;
|
||||||
|
#endif
|
||||||
|
strcpy(name1, name2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!didSwap) break;
|
if (!didSwap) break;
|
||||||
}
|
}
|
||||||
|
@ -944,10 +992,10 @@ void CardReader::setroot() {
|
||||||
sortshort = new char*[1];
|
sortshort = new char*[1];
|
||||||
isDir = new uint8_t[1];
|
isDir = new uint8_t[1];
|
||||||
#endif
|
#endif
|
||||||
getfilename(0);
|
selectFileByIndex(0);
|
||||||
SET_SORTNAME(0);
|
SET_SORTNAME(0);
|
||||||
SET_SORTSHORT(0);
|
SET_SORTSHORT(0);
|
||||||
isDir[0] = flag.filenameIsDir ? 0x01 : 0x00;
|
isDir[0] = flag.filenameIsDir;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,6 +1032,9 @@ uint16_t CardReader::get_num_Files() {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Return from procedure or close out the Print Job
|
||||||
|
//
|
||||||
void CardReader::printingHasFinished() {
|
void CardReader::printingHasFinished() {
|
||||||
planner.synchronize();
|
planner.synchronize();
|
||||||
file.close();
|
file.close();
|
||||||
|
|
|
@ -33,8 +33,6 @@
|
||||||
|
|
||||||
#include "SdFile.h"
|
#include "SdFile.h"
|
||||||
|
|
||||||
enum LsAction : uint8_t { LS_SerialPrint, LS_Count, LS_GetFilename };
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool saving:1,
|
bool saving:1,
|
||||||
logging:1,
|
logging:1,
|
||||||
|
@ -51,48 +49,80 @@ typedef struct {
|
||||||
|
|
||||||
class CardReader {
|
class CardReader {
|
||||||
public:
|
public:
|
||||||
|
static card_flags_t flag; // Flags (above)
|
||||||
|
static char filename[FILENAME_LENGTH], // DOS 8.3 filename of the selected item
|
||||||
|
longFilename[LONG_FILENAME_LENGTH]; // Long name of the selected item
|
||||||
|
|
||||||
|
// Fast! binary file transfer
|
||||||
|
#if ENABLED(BINARY_FILE_TRANSFER)
|
||||||
|
#if NUM_SERIAL > 1
|
||||||
|
static int8_t transfer_port_index;
|
||||||
|
#else
|
||||||
|
static constexpr int8_t transfer_port_index = 0;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// // // Methods // // //
|
||||||
|
|
||||||
CardReader();
|
CardReader();
|
||||||
|
|
||||||
static void mount();
|
static SdFile getroot() { return root; }
|
||||||
static void write_command(char *buf);
|
|
||||||
|
|
||||||
|
static void mount();
|
||||||
|
static void release();
|
||||||
|
static inline bool isMounted() { return flag.mounted; }
|
||||||
|
static void ls();
|
||||||
|
|
||||||
|
// SD Card Logging
|
||||||
|
static void openLogFile(char * const path);
|
||||||
|
static void write_command(char * const buf);
|
||||||
|
|
||||||
|
// Auto-Start files
|
||||||
|
static int8_t autostart_index; // Index of autoX.g files
|
||||||
static void beginautostart();
|
static void beginautostart();
|
||||||
static void checkautostart();
|
static void checkautostart();
|
||||||
|
|
||||||
|
// Basic file ops
|
||||||
static void openFile(char * const path, const bool read, const bool subcall=false);
|
static void openFile(char * const path, const bool read, const bool subcall=false);
|
||||||
static void openLogFile(char * const path);
|
|
||||||
static void removeFile(const char * const name);
|
|
||||||
static void closefile(const bool store_location=false);
|
static void closefile(const bool store_location=false);
|
||||||
static void release();
|
static void removeFile(const char * const name);
|
||||||
static void openAndPrintFile(const char *name);
|
|
||||||
|
static inline char* longest_filename() { return longFilename[0] ? longFilename : filename; }
|
||||||
|
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
||||||
|
static void printLongPath(char * const path); // Used by M33
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Working Directory for SD card menu
|
||||||
|
static void cdroot();
|
||||||
|
static void cd(const char *relpath);
|
||||||
|
static int8_t cdup();
|
||||||
|
static uint16_t countFilesInWorkDir();
|
||||||
|
static uint16_t get_num_Files();
|
||||||
|
|
||||||
|
// Select a file
|
||||||
|
static void selectFileByIndex(const uint16_t nr);
|
||||||
|
static void selectFileByName(const char* const match);
|
||||||
|
|
||||||
|
// Print job
|
||||||
|
static void openAndPrintFile(const char *name); // (working directory)
|
||||||
|
static void printingHasFinished();
|
||||||
|
static void getAbsFilename(char *dst);
|
||||||
static void startFileprint();
|
static void startFileprint();
|
||||||
|
static void printFilename();
|
||||||
static void stopSDPrint(
|
static void stopSDPrint(
|
||||||
#if SD_RESORT
|
#if SD_RESORT
|
||||||
const bool re_sort=false
|
const bool re_sort=false
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
static void report_status();
|
static void report_status();
|
||||||
static void printingHasFinished();
|
static inline void pauseSDPrint() { flag.sdprinting = false; }
|
||||||
static void printFilename();
|
static inline bool isPaused() { return isFileOpen() && !flag.sdprinting; }
|
||||||
|
static inline bool isPrinting() { return flag.sdprinting; }
|
||||||
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
static inline uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
|
||||||
static void printLongPath(char *path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void getfilename(uint16_t nr, const char* const match=nullptr);
|
|
||||||
static uint16_t countFilesInWorkDir();
|
|
||||||
|
|
||||||
static void getAbsFilename(char *t);
|
|
||||||
|
|
||||||
static void ls();
|
|
||||||
static void chdir(const char *relpath);
|
|
||||||
static int8_t updir();
|
|
||||||
static void setroot();
|
|
||||||
|
|
||||||
|
// Helper for open and remove
|
||||||
static const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo=false);
|
static const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo=false);
|
||||||
|
|
||||||
static uint16_t get_num_Files();
|
|
||||||
|
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
static void presort();
|
static void presort();
|
||||||
static void getfilename_sorted(const uint16_t nr);
|
static void getfilename_sorted(const uint16_t nr);
|
||||||
|
@ -102,7 +132,7 @@ public:
|
||||||
//FORCE_INLINE static void setSortReverse(bool b) { sort_reverse = b; }
|
//FORCE_INLINE static void setSortReverse(bool b) { sort_reverse = b; }
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { getfilename(nr); }
|
FORCE_INLINE static void getfilename_sorted(const uint16_t nr) { selectFileByIndex(nr); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLED(POWER_LOSS_RECOVERY)
|
#if ENABLED(POWER_LOSS_RECOVERY)
|
||||||
|
@ -111,17 +141,12 @@ public:
|
||||||
static void removeJobRecoveryFile();
|
static void removeJobRecoveryFile();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void pauseSDPrint() { flag.sdprinting = false; }
|
|
||||||
static inline bool isMounted() { return flag.mounted; }
|
|
||||||
static inline bool isFileOpen() { return isMounted() && file.isOpen(); }
|
static inline bool isFileOpen() { return isMounted() && file.isOpen(); }
|
||||||
static inline bool isPaused() { return isFileOpen() && !flag.sdprinting; }
|
|
||||||
static inline bool isPrinting() { return flag.sdprinting; }
|
|
||||||
static inline bool eof() { return sdpos >= filesize; }
|
|
||||||
static inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
|
|
||||||
static inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
|
|
||||||
static inline uint32_t getIndex() { return sdpos; }
|
static inline uint32_t getIndex() { return sdpos; }
|
||||||
static inline uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
|
static inline bool eof() { return sdpos >= filesize; }
|
||||||
|
static inline void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
|
||||||
static inline char* getWorkDirName() { workDir.getDosName(filename); return filename; }
|
static inline char* getWorkDirName() { workDir.getDosName(filename); return filename; }
|
||||||
|
static inline int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
|
||||||
static inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; }
|
static inline int16_t read(void* buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; }
|
||||||
static inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; }
|
static inline int16_t write(void* buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; }
|
||||||
|
|
||||||
|
@ -139,27 +164,16 @@ public:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline char* longest_filename() { return longFilename[0] ? longFilename : filename; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static card_flags_t flag;
|
|
||||||
static char filename[FILENAME_LENGTH], longFilename[LONG_FILENAME_LENGTH];
|
|
||||||
static int8_t autostart_index;
|
|
||||||
static SdFile getroot() { return root; }
|
|
||||||
|
|
||||||
#if ENABLED(BINARY_FILE_TRANSFER)
|
|
||||||
#if NUM_SERIAL > 1
|
|
||||||
static int8_t transfer_port_index;
|
|
||||||
#else
|
|
||||||
static constexpr int8_t transfer_port_index = 0;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//
|
||||||
|
// Working directory and parents
|
||||||
|
//
|
||||||
static SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
|
static SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
|
||||||
static uint8_t workDirDepth;
|
static uint8_t workDirDepth;
|
||||||
|
|
||||||
// Sort files and folders alphabetically.
|
//
|
||||||
|
// Alphabetical file and folder sorting
|
||||||
|
//
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
static uint16_t sort_count; // Count of sorted items in the current directory
|
static uint16_t sort_count; // Count of sorted items in the current directory
|
||||||
#if ENABLED(SDSORT_GCODE)
|
#if ENABLED(SDSORT_GCODE)
|
||||||
|
@ -188,6 +202,7 @@ private:
|
||||||
|
|
||||||
// If using dynamic ram for names, allocate on the heap.
|
// If using dynamic ram for names, allocate on the heap.
|
||||||
#if ENABLED(SDSORT_CACHE_NAMES)
|
#if ENABLED(SDSORT_CACHE_NAMES)
|
||||||
|
static uint16_t nrFiles; // Cache the total count
|
||||||
#if ENABLED(SDSORT_DYNAMIC_RAM)
|
#if ENABLED(SDSORT_DYNAMIC_RAM)
|
||||||
static char **sortshort, **sortnames;
|
static char **sortshort, **sortnames;
|
||||||
#else
|
#else
|
||||||
|
@ -216,25 +231,21 @@ private:
|
||||||
static SdVolume volume;
|
static SdVolume volume;
|
||||||
static SdFile file;
|
static SdFile file;
|
||||||
|
|
||||||
|
static uint32_t filesize, sdpos;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Procedure calls to other files
|
||||||
|
//
|
||||||
#ifndef SD_PROCEDURE_DEPTH
|
#ifndef SD_PROCEDURE_DEPTH
|
||||||
#define SD_PROCEDURE_DEPTH 1
|
#define SD_PROCEDURE_DEPTH 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t file_subcall_ctr;
|
static uint8_t file_subcall_ctr;
|
||||||
static uint32_t filespos[SD_PROCEDURE_DEPTH];
|
static uint32_t filespos[SD_PROCEDURE_DEPTH];
|
||||||
static char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
static char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
||||||
|
|
||||||
static uint32_t filesize, sdpos;
|
//
|
||||||
|
// SD Auto Reporting
|
||||||
static LsAction lsAction; //stored for recursion.
|
//
|
||||||
static uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
|
|
||||||
static char *diveDirName;
|
|
||||||
static void lsDive(const char *prepend, SdFile parent, const char * const match=nullptr);
|
|
||||||
|
|
||||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
|
||||||
static void flush_presort();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLED(AUTO_REPORT_SD_STATUS)
|
#if ENABLED(AUTO_REPORT_SD_STATUS)
|
||||||
static uint8_t auto_report_sd_interval;
|
static uint8_t auto_report_sd_interval;
|
||||||
static millis_t next_sd_report_ms;
|
static millis_t next_sd_report_ms;
|
||||||
|
@ -242,6 +253,19 @@ private:
|
||||||
static int8_t auto_report_port;
|
static int8_t auto_report_port;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Directory items
|
||||||
|
//
|
||||||
|
static bool is_dir_or_gcode(const dir_t &p);
|
||||||
|
static int countItems(SdFile dir);
|
||||||
|
static void selectByIndex(SdFile dir, const uint8_t index);
|
||||||
|
static void selectByName(SdFile dir, const char * const match);
|
||||||
|
static void printListing(SdFile parent, const char * const prepend=nullptr);
|
||||||
|
|
||||||
|
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||||
|
static void flush_presort();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
|
||||||
|
|
Reference in a new issue