From 6901445592dd9e9b164b00b4ff432f0e89f63511 Mon Sep 17 00:00:00 2001 From: Scott Lahteine <sourcetree@thinkyhead.com> Date: Wed, 26 Nov 2014 07:17:47 -0800 Subject: [PATCH] Improvements, more SORT_USES_MORE_RAM With this option, always keeps the dir in RAM, doubling as a cache for getfilename. A board with only 8K of SRAM is cutting it very close. --- Marlin/cardreader.cpp | 137 +++++++++++++++++++++--------------------- Marlin/cardreader.h | 18 +++--- Marlin/ultralcd.cpp | 4 +- 3 files changed, 78 insertions(+), 81 deletions(-) diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp index 10a4e6b1cf..5d465f47a4 100644 --- a/Marlin/cardreader.cpp +++ b/Marlin/cardreader.cpp @@ -11,8 +11,7 @@ CardReader::CardReader() { - #if defined(SDCARD_SORT_ALPHA) && SORT_USES_MORE_RAM - sortnames = NULL; + #ifdef SDCARD_SORT_ALPHA sort_count = 0; #endif filesize = 0; @@ -37,19 +36,15 @@ CardReader::CardReader() autostart_atmillis=millis()+5000; } -char *createFilename(char *buffer,const dir_t &p) //buffer>12characters +char *createFilename(char *buffer, const dir_t &p) //buffer>12characters { char *pos=buffer; - for (uint8_t i = 0; i < 11; i++) - { - if (p.name[i] == ' ')continue; - if (i == 8) - { - *pos++='.'; - } - *pos++=p.name[i]; + for (uint8_t i = 0; i < 11; i++) { + if (p.name[i] == ' ') continue; + if (i == 8) *pos++ = '.'; + *pos++ = p.name[i]; } - *pos++=0; + *pos++ = 0; return buffer; } @@ -59,7 +54,7 @@ void CardReader::lsDive(const char *prepend,SdFile parent) dir_t p; uint8_t cnt=0; - while (parent.readDir(p, diveFilename) > 0) + while (parent.readDir(p, longFilename) > 0) { if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint { @@ -96,8 +91,8 @@ void CardReader::lsDive(const char *prepend,SdFile parent) { if (p.name[0] == DIR_NAME_FREE) break; if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (diveFilename[0] != '\0' && - (diveFilename[0] == '.' || diveFilename[0] == '_')) continue; + if (longFilename[0] != '\0' && + (longFilename[0] == '.' || longFilename[0] == '_')) continue; if ( p.name[0] == '.') { if ( p.name[1] != '.') @@ -556,21 +551,20 @@ void CardReader::closefile(bool store_location) } -void CardReader::getfilename(const uint8_t nr) +void CardReader::getfilename(const uint16_t nr) { - #if defined(SDCARD_SORT_ALPHA) && SORT_USES_MORE_RAM + #if defined(SDCARD_SORT_ALPHA) && SORT_USES_RAM && SORT_USES_MORE_RAM if (nr < sort_count) { - strcpy(diveFilename, sortnames[nr]); + strcpy(longFilename, sortnames[nr]); + filenameIsDir = isDir[nr]; return; } #endif - curDir=&workDir; lsAction=LS_GetFilename; nrFiles=nr; curDir->rewind(); lsDive("",*curDir); - } uint16_t CardReader::getnrfilenames() @@ -631,12 +625,8 @@ void CardReader::updir() /** * Get the name of a file in the current directory by sort-index */ -void CardReader::getfilename_sorted(const uint8_t nr) { - #if SORT_USES_MORE_RAM - getfilename(nr < sort_count ? sort_order[nr] : nr); - #else - getfilename(nr < SORT_LIMIT ? sort_order[nr] : nr); - #endif +void CardReader::getfilename_sorted(const uint16_t nr) { + getfilename(nr < sort_count ? sort_order[nr] : nr); } /** @@ -656,68 +646,73 @@ void CardReader::presort() if (fileCnt > SORT_LIMIT) fileCnt = SORT_LIMIT; - #if SORT_USES_MORE_RAM - sortnames = (char**)malloc(fileCnt * sizeof(char*)); - sort_count = fileCnt; - #elif SORT_USES_RAM - char *sortnames[fileCnt]; - #if FOLDER_SORTING != 0 - uint8_t isdir[fileCnt]; + #if SORT_USES_RAM + #if SORT_USES_MORE_RAM + sortnames = (char**)calloc(fileCnt, sizeof(char*)); + #else + char *sortnames[fileCnt]; #endif #else - char sortname[LONG_FILENAME_LENGTH+1]; + char name1[LONG_FILENAME_LENGTH+1]; #endif + #if FOLDER_SORTING != 0 + #if SORT_USES_RAM && SORT_USES_MORE_RAM + isDir = (uint8_t*)calloc(fileCnt, sizeof(uint8_t)); + #else + uint8_t isDir[fileCnt]; + #endif + #endif + + sort_count = fileCnt; + sort_order = new uint8_t[fileCnt]; + if (fileCnt > 1) { - // Init sort order [and get filenames] - for (int i=0; i<fileCnt; i++) { - int byte=i/8, bit=1<<(i%8); + // Init sort order. If using RAM then read all filenames now. + for (uint16_t i=0; i<fileCnt; i++) { sort_order[i] = i; #if SORT_USES_RAM getfilename(i); - char *name = diveFilename[0] ? diveFilename : filename; - // SERIAL_ECHOPGM("--- "); - // SERIAL_ECHOLN(name); - sortnames[i] = (char*)malloc(strlen(name) + 1); - strcpy(sortnames[i], name); + sortnames[i] = strdup(longFilename[0] ? longFilename : filename); + // char out[30]; + // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]); + // SERIAL_ECHOLN(out); #if FOLDER_SORTING != 0 - isdir[i] = filenameIsDir; + isDir[i] = filenameIsDir; #endif #endif } // Bubble Sort - for (uint8_t i=fileCnt; --i;) { + for (uint16_t i=fileCnt; --i;) { bool cmp, didSwap = false; - for (uint8_t j=0; j<i; ++j) { - int s1 = j, s2 = j+1, o1 = sort_order[s1], o2 = sort_order[s2]; + for (uint16_t j=0; j<i; ++j) { + uint16_t s1 = j, s2 = j+1, o1 = sort_order[s1], o2 = sort_order[s2]; #if SORT_USES_RAM #if FOLDER_SORTING != 0 - cmp = (isdir[o1] == isdir[o2]) ? (strcasecmp(sortnames[o1], sortnames[o2]) > 0) : isdir[FOLDER_SORTING > 0 ? o1 : o2]; + cmp = (isDir[o1] == isDir[o2]) ? (strcasecmp(sortnames[o1], sortnames[o2]) > 0) : isDir[FOLDER_SORTING > 0 ? o1 : o2]; #else - cmp = strcasecmp(sortnames[o1], sortnames[o2]) > 0); + cmp = strcasecmp(sortnames[o1], sortnames[o2]) > 0; #endif #else getfilename(o1); + strcpy(name1, longFilename[0] ? longFilename : filename); #if FOLDER_SORTING != 0 bool dir1 = filenameIsDir; #endif - char *name = diveFilename[0] ? diveFilename : filename; - strcpy(sortname, name); getfilename(o2); - name = diveFilename[0] ? diveFilename : filename; + char *name2 = longFilename[0] ? longFilename : filename; #if FOLDER_SORTING != 0 - cmp = (dir1 == filenameIsDir) ? (strcasecmp(sortname, name) > 0) : (FOLDER_SORTING > 0 ? dir1 : !dir1); + cmp = (dir1 == filenameIsDir) ? (strcasecmp(name1, name2) > 0) : (FOLDER_SORTING > 0 ? dir1 : !dir1); #else - cmp = strcasecmp(sortname, name) > 0); + cmp = strcasecmp(name1, name2) > 0; #endif #endif if (cmp) { - // SERIAL_ECHOPGM("Swap "); - // SERIAL_ECHOLN(sortnames[o1]); - // SERIAL_ECHOPGM(" for "); - // SERIAL_ECHOLN(sortnames[o2]); + // char out[LONG_FILENAME_LENGTH*2+20]; + // sprintf_P(out, PSTR("Swap %i %s for %i %s"), o1, sortnames[o1], o2, sortnames[o2]); + // SERIAL_ECHOLN(out); sort_order[s1] = o2; sort_order[s2] = o1; didSwap = true; @@ -727,30 +722,32 @@ void CardReader::presort() } #if SORT_USES_RAM && !SORT_USES_MORE_RAM - for (int i=0; i < fileCnt; ++i) free(sortnames[i]); + for (uint16_t i=0; i<fileCnt; ++i) free(sortnames[i]); #endif } else { sort_order[0] = 0; + #if SORT_USES_RAM && SORT_USES_MORE_RAM + sortnames = (char**)malloc(sizeof(char*)); + isDir = (uint8_t*)malloc(sizeof(uint8_t)); + getfilename(0); + sortnames[0] = strdup(longFilename[0] ? longFilename : filename); + isDir[0] = filenameIsDir; + #endif } } } void CardReader::flush_presort() { - #if SORT_USES_MORE_RAM - if (sort_count > 0) { - for (int i=0; i < sort_count; ++i) { - free(sortnames[i]); - sort_order[i] = i; - } + if (sort_count > 0) { + #if SORT_USES_RAM && SORT_USES_MORE_RAM + for (uint8_t i=0; i<sort_count; ++i) free(sortnames[i]); free(sortnames); - sortnames = NULL; - sort_count = 0; - } - #else - for (int i=SORT_LIMIT; --i;) sort_order[i] = i; - #endif + #endif + delete sort_order; + sort_count = 0; + } } #endif // SDCARD_SORT_ALPHA diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h index 1d8d1b1fb6..6a74fe0661 100644 --- a/Marlin/cardreader.h +++ b/Marlin/cardreader.h @@ -6,7 +6,7 @@ #define MAX_DIR_DEPTH 10 // Maximum folder depth #define SORT_USES_RAM false // Buffer while sorting, else re-read from SD #define SORT_USES_MORE_RAM false // Always keep the directory in RAM -#define SORT_LIMIT 256 // Maximum number of sorted items +#define SORT_LIMIT 64 // Maximum number of sorted items #define FOLDER_SORTING -1 // -1=above 0=none 1=below #include "SdFile.h" @@ -32,7 +32,7 @@ public: void getStatus(); void printingHasFinished(); - void getfilename(const uint8_t nr); + void getfilename(const uint16_t nr); uint16_t getnrfilenames(); void getAbsFilename(char *t); @@ -46,7 +46,7 @@ public: #ifdef SDCARD_SORT_ALPHA void presort(); void flush_presort(); - void getfilename_sorted(const uint8_t nr); + void getfilename_sorted(const uint16_t nr); #endif @@ -60,21 +60,21 @@ public: public: bool saving; bool logging; - bool sdprinting ; + bool sdprinting; bool cardOK; char filename[FILENAME_LENGTH]; - char diveFilename[LONG_FILENAME_LENGTH]; + char longFilename[LONG_FILENAME_LENGTH]; bool filenameIsDir; int lastnr; //last number of the autostart; private: SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH]; uint16_t workDirDepth; #ifdef SDCARD_SORT_ALPHA + uint16_t sort_count; + uint8_t *sort_order; #if SORT_USES_MORE_RAM - uint16_t sort_count; char **sortnames; - #else - uint8_t sort_order[SORT_LIMIT]; + uint8_t *isDir; #endif #endif Sd2Card card; @@ -93,7 +93,7 @@ private: bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. LsAction lsAction; //stored for recursion. - int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. + 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. char* diveDirName; void lsDive(const char *prepend,SdFile parent); }; diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 981efdb606..f131499b94 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -970,10 +970,10 @@ void lcd_sdcard_menu() #endif if (card.filenameIsDir) { - MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.diveFilename); + MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename); } else { - MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.diveFilename); + MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename); } }else{ MENU_ITEM_DUMMY();