diff --git a/Firmware/Configuration_adv.h b/Firmware/Configuration_adv.h index e14cffd22..3c8cd365f 100644 --- a/Firmware/Configuration_adv.h +++ b/Firmware/Configuration_adv.h @@ -268,7 +268,8 @@ #define SDSORT_USES_STACK false // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.) #define SDSORT_CACHE_NAMES false // Keep sorted items in RAM longer for speedy performance. Most expensive option. #define SDSORT_DYNAMIC_RAM false // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use! - #define SDSORT_POINTERS false //stores adresses of filenames on stack + #define SDSORT_POINTERS false //stores adresses of filenames on stack + #define QUICKSORT #endif #if defined(SDCARD_SORT_ALPHA) diff --git a/Firmware/SdBaseFile.cpp b/Firmware/SdBaseFile.cpp index 11bc7b81d..f3b037981 100644 --- a/Firmware/SdBaseFile.cpp +++ b/Firmware/SdBaseFile.cpp @@ -1113,34 +1113,51 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) { int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) { int16_t n; // if not a directory file or miss-positioned return an error - if (!isDir() || (0X1F & curPosition_)) return -1; + if (!isDir() || (0X1F & curPosition_)) { + SERIAL_ECHOLNPGM("return -1"); + return -1; + } //If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly. if (longFilename != NULL) { + // SERIAL_ECHOPGM("; reseting long filename; "); longFilename[0] = '\0'; } - + //int i_pom = 0; while (1) { n = read(dir, sizeof(dir_t)); + /*SERIAL_ECHOPGM("Jsem uvnitr: "); MYSERIAL.print(n); uint32_t pom = curPosition(); SERIAL_ECHOPGM(": "); MYSERIAL.println(pom, 10);*/ + //SERIAL_ECHOPGM("i: "); + //MYSERIAL.println(i_pom++); + if (n != sizeof(dir_t)) return n == 0 ? 0 : -1; // last entry if DIR_NAME_FREE - if (dir->name[0] == DIR_NAME_FREE) return 0; + if (dir->name[0] == DIR_NAME_FREE) { + return 0; + SERIAL_ECHOLNPGM("DIR_NAME_FREE"); + } // skip empty entries and entry for . and .. - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; + if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') { + //SERIAL_ECHOLNPGM("Empty entry, . or .."); + continue; + } //Fill the long filename if we have a long filename entry, // long filename entries are stored before the actual filename. if (DIR_IS_LONG_NAME(dir) && longFilename != NULL) { + //SERIAL_ECHOLNPGM("We have long filename entry"); vfat_t *VFAT = (vfat_t*)dir; //Sanity check the VFAT entry. The first cluster is always set to zero. And th esequence number should be higher then 0 if (VFAT->firstClusterLow == 0 && (VFAT->sequenceNumber & 0x1F) > 0 && (VFAT->sequenceNumber & 0x1F) <= MAX_VFAT_ENTRIES) { + //SERIAL_ECHOPGM("VFAT Entries no:"); + //MYSERIAL.println(VFAT->sequenceNumber & 0x1F); //TODO: Store the filename checksum to verify if a none-long filename aware system modified the file table. n = ((VFAT->sequenceNumber & 0x1F) - 1) * 13; longFilename[n+0] = VFAT->name1[0]; @@ -1157,8 +1174,11 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) { longFilename[n+11] = VFAT->name3[0]; longFilename[n+12] = VFAT->name3[1]; //If this VFAT entry is the last one, add a NUL terminator at the end of the string - if (VFAT->sequenceNumber & 0x40) - longFilename[n+13] = '\0'; + if (VFAT->sequenceNumber & 0x40) { + longFilename[n + 13] = '\0'; + //SERIAL_ECHOPGM("LOng F"); + //MYSERIAL.println(longFilename); + } } } // return if normal file or subdirectory diff --git a/Firmware/cardreader.cpp b/Firmware/cardreader.cpp index ebee867e6..e81409aa8 100644 --- a/Firmware/cardreader.cpp +++ b/Firmware/cardreader.cpp @@ -65,8 +65,13 @@ void CardReader::lsDive_pointer(const char *prepend, SdFile parent, const char * //parent.seekSet = // Read the next entry from a directory + //SERIAL_ECHOPGM("Cur pos before.: "); + //uint32_t pom = parent.curPosition(); + //MYSERIAL.println(pom, 10); parent.readDir(p, longFilename); - + //SERIAL_ECHOPGM("Cur pos.: "); + //pom = parent.curPosition(); + //MYSERIAL.println(pom, 10); uint8_t pn0 = p.name[0]; @@ -103,9 +108,9 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m //SERIAL_ECHOPGM(": "); //MYSERIAL.print(pom, 10); //SERIAL_ECHOPGM("; "); - /*SERIAL_ECHOPGM("Cur pos.: "); - uint32_t pom = parent.curPosition(); - MYSERIAL.println(pom, 10);*/ + //SERIAL_ECHOPGM("Cur pos.: "); + //uint32_t pom = parent.curPosition(); + //MYSERIAL.println(pom, 10); // If the entry is a directory and the action is LS_SerialPrint if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { @@ -168,6 +173,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m case LS_GetFilename: //SERIAL_ECHOPGM("File: "); createFilename(filename, p); + //MYSERIAL.println(p.name); /*MYSERIAL.println(filename); SERIAL_ECHOPGM("Write date: "); writeDate = p.lastWriteDate; @@ -688,24 +694,12 @@ void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) void CardReader::getfilename_simple(uint32_t position, const char * const match/*=NULL*/) { - //SERIAL_ECHOPGM("FILE NR:"); - //MYSERIAL.println(position); curDir = &workDir; - //curDir = curDir + nr * 32 * 8; //32 bytes per entry lsAction = LS_GetFilename; - //nrFiles = nr; + nrFiles = 0; //curDir->rewind(); curDir->seekSet(position); - //curDir->setpos(32*nr); - lsDive_pointer("", *curDir, match); - /*SERIAL_ECHOPGM("; Position:"); - uint32_t pom = curDir->curPosition(); - MYSERIAL.print(pom, 10); - SERIAL_ECHOPGM("; Cluster:"); - MYSERIAL.println(curDir->curCluster());*/ - - - + lsDive("", *curDir, match); } @@ -771,6 +765,56 @@ void CardReader::getfilename_sorted(const uint16_t nr) { ); } + +void CardReader::swap(uint8_t array[], uint8_t left, uint8_t right) { + uint8_t tmp = array[right]; + array[right] = array[left]; + array[left] = tmp; + //SERIAL_ECHOLNPGM("Did swap"); +} + +void CardReader::quicksort(uint8_t array[], uint8_t left, uint8_t right, uint32_t positions[]) { + if (left < right) { + char name_left[LONG_FILENAME_LENGTH + 1]; + char name_i[LONG_FILENAME_LENGTH + 1]; + uint16_t creation_time_left; + uint16_t creation_date_left; + + uint8_t boundary = left; + for (uint8_t i = left+1; i < right; i++) { + uint8_t o_left = array[left]; + uint8_t o_i = array[i]; + getfilename_simple(positions[o_left]); + strcpy(name_left, LONGEST_FILENAME); // save (or getfilename below will trounce it) + creation_date_left = creationDate; + creation_time_left = creationTime; + getfilename_simple(positions[o_i]); + + /*SERIAL_ECHOLNPGM(" "); + MYSERIAL.print(int(o_left)); + SERIAL_ECHOPGM(": "); + MYSERIAL.print(positions[o_left]); + SERIAL_ECHOPGM(": "); + MYSERIAL.println(name_left); + MYSERIAL.print(int(o_i)); + SERIAL_ECHOPGM(": "); + MYSERIAL.print(positions[o_i]); + SERIAL_ECHOPGM(": "); + MYSERIAL.println(LONGEST_FILENAME);*/ + strcpy(name_i, LONGEST_FILENAME); + + + if (strcasecmp(name_left, name_i) > 0) { + swap(array, i, ++boundary); + } + } + swap(array, left, boundary); + quicksort(array, left, boundary, positions); + quicksort(array, boundary + 1, right, positions); + } +} + + /** * Read all the files and produce a sort key * @@ -842,6 +886,7 @@ void CardReader::presort() { #else // !SDSORT_USES_RAM // uint32_t clusters [fileCnt]; uint32_t positions [fileCnt]; + // char *names[fileCnt]; // By default re-read the names from SD for every compare @@ -852,16 +897,32 @@ void CardReader::presort() { uint16_t creation_date_bckp; #endif - + position = 0; if (fileCnt > 1) { // Init sort order. for (uint16_t i = 0; i < fileCnt; i++) { sort_order[i] = i; - getfilename(i); + /*MYSERIAL.print(i); + SERIAL_ECHOPGM(": "); + MYSERIAL.print(position); + SERIAL_ECHOPGM("; "); + MYSERIAL.print(cluster); + SERIAL_ECHOPGM(" ");*/ + + positions[i] = position; + getfilename(i); + //MYSERIAL.print(LONGEST_FILENAME); + //names[i] = //clusters[i] = cluster; - positions[i] = position-96; + //if (longFilename[0]) SERIAL_ECHOPGM("; Long; "); + //MYSERIAL.println(i); - //MYSERIAL.println(position); + /*SERIAL_ECHOPGM("; "); + MYSERIAL.print(position); + SERIAL_ECHOPGM("; "); + MYSERIAL.print(positions[i]); + SERIAL_ECHOPGM("; "); + MYSERIAL.println(cluster);*/ // If using RAM then read all filenames now. #if SDSORT_USES_RAM getfilename(i); @@ -892,9 +953,12 @@ void CardReader::presort() { #endif #endif } - SERIAL_ECHOPGM("Mezicas:"); - MYSERIAL.println(millis() - start_time); - // Bubble Sort + /*SERIAL_ECHOPGM("Mezicas:"); + MYSERIAL.println(millis() - start_time);*/ + +#ifdef QUICKSORT + quicksort(sort_order, 0, fileCnt - 1, positions); +#else //Qicksort not defined, use Bubble Sort uint16_t counter = 0; for (uint16_t i = fileCnt; --i;) { bool didSwap = false; @@ -982,7 +1046,7 @@ void CardReader::presort() { } if (!didSwap) break; } //end of bubble sort loop - +#endif // Using RAM but not keeping names around #if (SDSORT_USES_RAM && !SDSORT_CACHE_NAMES) #if SDSORT_DYNAMIC_RAM diff --git a/Firmware/cardreader.h b/Firmware/cardreader.h index f043f3b44..b2fa4efea 100644 --- a/Firmware/cardreader.h +++ b/Firmware/cardreader.h @@ -45,6 +45,8 @@ public: #ifdef SDCARD_SORT_ALPHA void presort(); + void swap(uint8_t array[], uint8_t left, uint8_t right); + void quicksort(uint8_t array[], uint8_t left, uint8_t right, uint32_t positions[]); void getfilename_sorted(const uint16_t nr); #if SDSORT_GCODE FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }