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.
This commit is contained in:
		
							parent
							
								
									2b54eeb897
								
							
						
					
					
						commit
						725ba8d01e
					
				| @ -11,8 +11,7 @@ | |||||||
| 
 | 
 | ||||||
| CardReader::CardReader() | CardReader::CardReader() | ||||||
| { | { | ||||||
|   #if defined(SDCARD_SORT_ALPHA) && SORT_USES_MORE_RAM |   #ifdef SDCARD_SORT_ALPHA | ||||||
|    sortnames = NULL; |  | ||||||
|    sort_count = 0; |    sort_count = 0; | ||||||
|   #endif |   #endif | ||||||
|    filesize = 0; |    filesize = 0; | ||||||
| @ -37,19 +36,15 @@ CardReader::CardReader() | |||||||
|   autostart_atmillis=millis()+5000; |   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; |   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; |     if (i == 8) *pos++ = '.'; | ||||||
|     if (i == 8)  |     *pos++ = p.name[i]; | ||||||
|     { |  | ||||||
|       *pos++='.'; |  | ||||||
|     } |  | ||||||
|     *pos++=p.name[i]; |  | ||||||
|   } |   } | ||||||
|   *pos++=0; |   *pos++ = 0; | ||||||
|   return buffer; |   return buffer; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -59,7 +54,7 @@ void  CardReader::lsDive(const char *prepend,SdFile parent) | |||||||
|   dir_t p; |   dir_t p; | ||||||
|   uint8_t cnt=0; |   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
 |     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_FREE) break; | ||||||
|       if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; |       if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; | ||||||
|       if (diveFilename[0] != '\0' && |       if (longFilename[0] != '\0' && | ||||||
|           (diveFilename[0] == '.' || diveFilename[0] == '_')) continue; |           (longFilename[0] == '.' || longFilename[0] == '_')) continue; | ||||||
|       if ( p.name[0] == '.') |       if ( p.name[0] == '.') | ||||||
|       { |       { | ||||||
|         if ( p.name[1] != '.') |         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) { |     if (nr < sort_count) { | ||||||
|       strcpy(diveFilename, sortnames[nr]); |       strcpy(longFilename, sortnames[nr]); | ||||||
|  |       filenameIsDir = isDir[nr]; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|   #endif |   #endif | ||||||
| 
 |  | ||||||
|   curDir=&workDir; |   curDir=&workDir; | ||||||
|   lsAction=LS_GetFilename; |   lsAction=LS_GetFilename; | ||||||
|   nrFiles=nr; |   nrFiles=nr; | ||||||
|   curDir->rewind(); |   curDir->rewind(); | ||||||
|   lsDive("",*curDir); |   lsDive("",*curDir); | ||||||
|    |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint16_t CardReader::getnrfilenames() | uint16_t CardReader::getnrfilenames() | ||||||
| @ -631,12 +625,8 @@ void CardReader::updir() | |||||||
| /**
 | /**
 | ||||||
|  * Get the name of a file in the current directory by sort-index |  * Get the name of a file in the current directory by sort-index | ||||||
|  */ |  */ | ||||||
| void CardReader::getfilename_sorted(const uint8_t nr) { | void CardReader::getfilename_sorted(const uint16_t nr) { | ||||||
|   #if SORT_USES_MORE_RAM |   getfilename(nr < sort_count ? sort_order[nr] : nr); | ||||||
|     getfilename(nr < sort_count ? sort_order[nr] : nr); |  | ||||||
|   #else |  | ||||||
|     getfilename(nr < SORT_LIMIT ? sort_order[nr] : nr); |  | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -656,68 +646,73 @@ void CardReader::presort() | |||||||
| 
 | 
 | ||||||
|     if (fileCnt > SORT_LIMIT) fileCnt = SORT_LIMIT; |     if (fileCnt > SORT_LIMIT) fileCnt = SORT_LIMIT; | ||||||
| 
 | 
 | ||||||
|     #if SORT_USES_MORE_RAM |     #if SORT_USES_RAM | ||||||
|       sortnames = (char**)malloc(fileCnt * sizeof(char*)); |       #if SORT_USES_MORE_RAM | ||||||
|       sort_count = fileCnt; |         sortnames = (char**)calloc(fileCnt, sizeof(char*)); | ||||||
|     #elif SORT_USES_RAM |       #else | ||||||
|       char *sortnames[fileCnt]; |         char *sortnames[fileCnt]; | ||||||
|       #if FOLDER_SORTING != 0 |  | ||||||
|         uint8_t isdir[fileCnt]; |  | ||||||
|       #endif |       #endif | ||||||
|     #else |     #else | ||||||
|       char sortname[LONG_FILENAME_LENGTH+1]; |       char name1[LONG_FILENAME_LENGTH+1]; | ||||||
|     #endif |     #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) { |     if (fileCnt > 1) { | ||||||
| 
 | 
 | ||||||
|       // Init sort order [and get filenames]
 |       // Init sort order. If using RAM then read all filenames now.
 | ||||||
|       for (int i=0; i<fileCnt; i++) { |       for (uint16_t i=0; i<fileCnt; i++) { | ||||||
|         int byte=i/8, bit=1<<(i%8); |  | ||||||
|         sort_order[i] = i; |         sort_order[i] = i; | ||||||
|         #if SORT_USES_RAM |         #if SORT_USES_RAM | ||||||
|           getfilename(i); |           getfilename(i); | ||||||
|           char *name = diveFilename[0] ? diveFilename : filename; |           sortnames[i] = strdup(longFilename[0] ? longFilename : filename); | ||||||
|           // SERIAL_ECHOPGM("--- ");
 |           // char out[30];
 | ||||||
|           // SERIAL_ECHOLN(name);
 |           // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
 | ||||||
|           sortnames[i] = (char*)malloc(strlen(name) + 1); |           // SERIAL_ECHOLN(out);
 | ||||||
|           strcpy(sortnames[i], name); |  | ||||||
|           #if FOLDER_SORTING != 0 |           #if FOLDER_SORTING != 0 | ||||||
|             isdir[i] = filenameIsDir; |             isDir[i] = filenameIsDir; | ||||||
|           #endif |           #endif | ||||||
|         #endif |         #endif | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Bubble Sort
 |       // Bubble Sort
 | ||||||
|       for (uint8_t i=fileCnt; --i;) { |       for (uint16_t i=fileCnt; --i;) { | ||||||
|         bool cmp, didSwap = false; |         bool cmp, didSwap = false; | ||||||
|         for (uint8_t j=0; j<i; ++j) { |         for (uint16_t j=0; j<i; ++j) { | ||||||
|           int s1 = j, s2 = j+1, o1 = sort_order[s1], o2 = sort_order[s2]; |           uint16_t s1 = j, s2 = j+1, o1 = sort_order[s1], o2 = sort_order[s2]; | ||||||
|           #if SORT_USES_RAM |           #if SORT_USES_RAM | ||||||
|             #if FOLDER_SORTING != 0 |             #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 |             #else | ||||||
|               cmp = strcasecmp(sortnames[o1], sortnames[o2]) > 0); |               cmp = strcasecmp(sortnames[o1], sortnames[o2]) > 0; | ||||||
|             #endif |             #endif | ||||||
|           #else |           #else | ||||||
|             getfilename(o1); |             getfilename(o1); | ||||||
|  |             strcpy(name1, longFilename[0] ? longFilename : filename); | ||||||
|             #if FOLDER_SORTING != 0 |             #if FOLDER_SORTING != 0 | ||||||
|               bool dir1 = filenameIsDir; |               bool dir1 = filenameIsDir; | ||||||
|             #endif |             #endif | ||||||
|             char *name = diveFilename[0] ? diveFilename : filename; |  | ||||||
|             strcpy(sortname, name); |  | ||||||
|             getfilename(o2); |             getfilename(o2); | ||||||
|             name = diveFilename[0] ? diveFilename : filename; |             char *name2 = longFilename[0] ? longFilename : filename; | ||||||
|             #if FOLDER_SORTING != 0 |             #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 |             #else | ||||||
|               cmp = strcasecmp(sortname, name) > 0); |               cmp = strcasecmp(name1, name2) > 0; | ||||||
|             #endif |             #endif | ||||||
|           #endif |           #endif | ||||||
|           if (cmp) { |           if (cmp) { | ||||||
|             // SERIAL_ECHOPGM("Swap ");
 |             // char out[LONG_FILENAME_LENGTH*2+20];
 | ||||||
|             // SERIAL_ECHOLN(sortnames[o1]);
 |             // sprintf_P(out, PSTR("Swap %i %s for %i %s"), o1, sortnames[o1], o2, sortnames[o2]);
 | ||||||
|             // SERIAL_ECHOPGM(" for ");
 |             // SERIAL_ECHOLN(out);
 | ||||||
|             // SERIAL_ECHOLN(sortnames[o2]);
 |  | ||||||
|             sort_order[s1] = o2; |             sort_order[s1] = o2; | ||||||
|             sort_order[s2] = o1; |             sort_order[s2] = o1; | ||||||
|             didSwap = true; |             didSwap = true; | ||||||
| @ -727,30 +722,32 @@ void CardReader::presort() | |||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       #if SORT_USES_RAM && !SORT_USES_MORE_RAM |       #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 |       #endif | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       sort_order[0] = 0; |       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() { | void CardReader::flush_presort() { | ||||||
|   #if SORT_USES_MORE_RAM |   if (sort_count > 0) { | ||||||
|     if (sort_count > 0) { |     #if SORT_USES_RAM && SORT_USES_MORE_RAM | ||||||
|       for (int i=0; i < sort_count; ++i) { |       for (uint8_t i=0; i<sort_count; ++i) free(sortnames[i]); | ||||||
|         free(sortnames[i]); |  | ||||||
|         sort_order[i] = i; |  | ||||||
|       } |  | ||||||
|       free(sortnames); |       free(sortnames); | ||||||
|       sortnames = NULL; |     #endif | ||||||
|       sort_count = 0; |     delete sort_order; | ||||||
|     } |     sort_count = 0; | ||||||
|   #else |   } | ||||||
|     for (int i=SORT_LIMIT; --i;) sort_order[i] = i; |  | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif // SDCARD_SORT_ALPHA
 | #endif // SDCARD_SORT_ALPHA
 | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
| #define MAX_DIR_DEPTH 10          // Maximum folder depth
 | #define MAX_DIR_DEPTH 10          // Maximum folder depth
 | ||||||
| #define SORT_USES_RAM false       // Buffer while sorting, else re-read from SD
 | #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_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
 | #define FOLDER_SORTING -1         // -1=above  0=none  1=below
 | ||||||
| 
 | 
 | ||||||
| #include "SdFile.h" | #include "SdFile.h" | ||||||
| @ -32,7 +32,7 @@ public: | |||||||
|   void getStatus(); |   void getStatus(); | ||||||
|   void printingHasFinished(); |   void printingHasFinished(); | ||||||
| 
 | 
 | ||||||
|   void getfilename(const uint8_t nr); |   void getfilename(const uint16_t nr); | ||||||
|   uint16_t getnrfilenames(); |   uint16_t getnrfilenames(); | ||||||
|    |    | ||||||
|   void getAbsFilename(char *t); |   void getAbsFilename(char *t); | ||||||
| @ -46,7 +46,7 @@ public: | |||||||
| #ifdef SDCARD_SORT_ALPHA | #ifdef SDCARD_SORT_ALPHA | ||||||
|   void presort(); |   void presort(); | ||||||
|   void flush_presort(); |   void flush_presort(); | ||||||
|   void getfilename_sorted(const uint8_t nr); |   void getfilename_sorted(const uint16_t nr); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -60,21 +60,21 @@ public: | |||||||
| public: | public: | ||||||
|   bool saving; |   bool saving; | ||||||
|   bool logging; |   bool logging; | ||||||
|   bool sdprinting ;   |   bool sdprinting; | ||||||
|   bool cardOK; |   bool cardOK; | ||||||
|   char filename[FILENAME_LENGTH]; |   char filename[FILENAME_LENGTH]; | ||||||
|   char diveFilename[LONG_FILENAME_LENGTH]; |   char longFilename[LONG_FILENAME_LENGTH]; | ||||||
|   bool filenameIsDir; |   bool filenameIsDir; | ||||||
|   int lastnr; //last number of the autostart;
 |   int lastnr; //last number of the autostart;
 | ||||||
| private: | private: | ||||||
|   SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH]; |   SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH]; | ||||||
|   uint16_t workDirDepth; |   uint16_t workDirDepth; | ||||||
| #ifdef SDCARD_SORT_ALPHA | #ifdef SDCARD_SORT_ALPHA | ||||||
|  |   uint16_t sort_count; | ||||||
|  |   uint8_t *sort_order; | ||||||
|   #if SORT_USES_MORE_RAM |   #if SORT_USES_MORE_RAM | ||||||
|     uint16_t sort_count; |  | ||||||
|     char **sortnames; |     char **sortnames; | ||||||
|   #else |     uint8_t *isDir; | ||||||
|     uint8_t sort_order[SORT_LIMIT]; |  | ||||||
|   #endif |   #endif | ||||||
| #endif | #endif | ||||||
|   Sd2Card card; |   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.
 |   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.
 |   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; |   char* diveDirName; | ||||||
|   void lsDive(const char *prepend,SdFile parent); |   void lsDive(const char *prepend,SdFile parent); | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -996,10 +996,10 @@ void lcd_sdcard_menu() | |||||||
|             #endif |             #endif | ||||||
| 
 | 
 | ||||||
|             if (card.filenameIsDir) { |             if (card.filenameIsDir) { | ||||||
|               MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.diveFilename); |               MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|               MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.diveFilename); |               MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename); | ||||||
|             } |             } | ||||||
|         }else{ |         }else{ | ||||||
|             MENU_ITEM_DUMMY(); |             MENU_ITEM_DUMMY(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user